Безопасно ли повторно использовать переменные внутри метода? - PullRequest
0 голосов
/ 20 февраля 2011

У меня есть массив типа string, который я хочу использовать внутри метода.

Мне нужно передать его в функцию, которая возвращает подмножество элементов массивапрошло.Чтобы получить возвращенный массив из функции, должен ли я объявить новый строковый массив или я могу безопасно повторно использовать тот же массив, который содержал нефильтрованный массив, для хранения фильтрованного массива ??

Также уточните, что, когда я передаюпеременная, подобная массиву функции, создает ли она новое пространство для массива в куче каждый раз, когда я передаю его в качестве параметра другим функциям, или просто использует то же пространство в куче и просто передает ссылку?Я предполагаю, что в случае массива он передает только ссылку, но в случае простых переменных он выделяет новое место в стеке, верно?

РЕДАКТИРОВАТЬ: Спасибо вам всем за отличные ответы и объяснения !!

Просьба также уточнить, нужно ли мне, если я повторно использую массив, установить нулевое значение в позиции, когда я заканчиваю подмножество массива?(На самом деле подмножество моего массива не рассчитывается напрямую из массива, но некоторые другие вычисления, поэтому Мне бы пришлось вручную установить значение NULL, в противном случае более старые элементы списка будут видны, верно ?? )

Ответы [ 4 ]

4 голосов
/ 20 февраля 2011

когда я передаю переменную, подобную массиву, функции, она создает новое пространство для массива в куче каждый раз, когда я передаю его в качестве параметра другим функциям, или просто использует то же пространство в куче и просто передает ссылку

Java полностью передается по значению , но с массивами и типами объектов передаваемое значение является ссылкой (указателем) на фактический объект, который не дублируется. Поэтому, когда вы передаете массив в функцию, копируется только ссылка ; сам массив не является. Вот почему, если функция изменяет содержимое массива, код, вызывающий функцию, видит изменения.

Пример:

// A method that changes the first entry in an array
void changeArray(String[] theArray) {
    theArray[0] = "Updated";
}

// A method that uses the above
void someMethod() {
    String[] foo = new String[3];
    foo[0] = "Original 0";
    foo[1] = "Original 1";
    foo[2] = "Original 2";

    this.changeArray(foo); // `changeArray` receives a *copy* of the reference
                           // held in `foo`; both references point to the same
                           // array

    System.out.println(foo[0]); // Prints "Updated"
}

Передача ссылки в метод аналогична присвоению ее другой ссылочной переменной:

String[] foo = new String[3]; // Create a new aaray, assign reference to `foo` variable
String[] bar = foo;           // Copy the reference into `bar` as well
foo[0] = "Hi there";          // Use the reference in `foo` to assign to the first element
System.out.println(bar[0]);   // Use the reference in `bar`, prints "Hi there"

По сути, ссылки - это значения (числа), которые сообщают JVM, где находятся данные для объекта. Таким образом, даже когда мы копируем ссылку (поскольку Java полностью передается по значению, значение ссылки передается функции), она все равно указывает на ту же память, что и оригинал.

Поскольку ссылка передается в функцию по значению, функция не может изменить ссылку вызывающего кода :

// A method that assigns a new reference; the calling code sees no change
void changeReference(String[] theArray) {
    theArray = new String[1];        // Now we're not using the caller's object anymore
    theArray[0] = "I was changed";
}

// A method that uses the above
void someMethod() {
    String[] foo = new String[3];
    foo[0] = "Original 0";
    foo[1] = "Original 1";
    foo[2] = "Original 2";

    this.changeReference(foo);
    System.out.println(foo[0]); // Prints "Original 0", our reference wasn't changed
}

Вы заметите, что в точности относится к примитивам:

void whatever(int a) {
    a = 5;
}
void someMethod() {
    int foo;

    foo = 3;
    whatever(foo);
    System.out.println(foo); // Prints 3, of course, not 5
}

... и фактически, объект ссылки (в отличие от объектов) являются примитивами.

... я должен объявить новый строковый массив или я могу безопасно повторно использовать тот же массив, который содержал нефильтрованный массив, для хранения фильтрованного массива

Вы можете безопасно использовать его повторно, если это уместно в рамках вашей функции. Может быть более целесообразным объявить новую переменную (например, filteredThingy), но это вопрос стиля и будет зависеть от ситуации.

1 голос
/ 20 февраля 2011

Возможно, это очень плохой стиль, очень подвержен ошибкам и небезопасен для будущих модификаций.

Вот пример.

public void foo(String[] args) {
    // do something with array.

    args = new String[] {"a", "b"};  // reuse of the array.

    // more code.

    for (Sring s : args) {
        // what will this loop get"? 
        // The answer is: a, b
        // but will you remember this fact in a month if "more code" above is 50 lines long?
    }

}
1 голос
/ 20 февраля 2011
String parentArray = {"S","B","R"};


// no need to use new operator to hold subSetArray.
String subSetArray = returnSubSet(parent);

public String[] returnSubSet(String[] _parent)
{
    return Arrays.copyOfRange(_parent,1,2);
}

, когда я передаю переменную, подобную массиву, функции, она создает новое пространство для массива в куче каждый раз, когда я передаю его в качестве параметра другим функциям или просто использует то же пространство вкуча и просто передает ссылку?

Answer      
 1. Object in Java are  Pass by reference by value
 2. when you pass an array to a function , a _parent variable will be created in stack and it points to the same Array Object in heap.

ОБНОВЛЕНИЯ: пример примитива

int global_scope_variable=10;

setValue(global_scope_variable);

public void setValue(int val)
{
    // val is visible only within this method.

    System.out.println(val);    // output is 10
    val=20;
    System.out.println(val);    // output is 20
    System.out.println(global_scope_variable);  // output is 10   
}
1 голос
/ 20 февраля 2011

Передача объектов по существу передает ссылки .Например, ваш массив будет существовать только в одном месте в памяти при передаче его между функциями.Вот работающий пример , иллюстрирующий это.

Если вам нравится, вы можете использовать тот же массив в своей программе.Обратите внимание, что изменения, внесенные в этот массив, будут видны всем объектам, имеющим одинаковую ссылку на этот массив.Если это нежелательно, вы должны объявить новый массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...