在方法中重用变量是否安全?

时间:2011-02-20 09:50:29

标签: java java-ee

我有一个类型字符串数组,我想在方法中重复使用。

我需要将它传递给一个函数,该函数返回传递的数组元素的子集。要从函数中捕获返回的数组,我应该声明一个新的字符串数组,还是可以安全地重新使用保存未过滤数组的相同数组来保存过滤数组?

还要澄清的是,当我将类似数组的变量传递给函数时,每当我将其作为参数传递给更多函数时,它会在堆中为数组创建一个新空间,或者只是它在堆和放大器中使用相同的空间;刚刚通过参考?我想在数组的情况下它只传递引用,但是在简单变量的情况下,它在堆栈上分配新的空间,对吗?

编辑:谢谢大家的精彩答案和解释!!

还请澄清一下,如果我重用数组,当我结束数组的子集时,是否需要在该位置设置null? (实际上我的数组的子集不是直接从数组计算出来的,而是一些其他的计算,所以我需要手动设置null,否则列表的旧元素会可见,对吗?

4 个答案:

答案 0 :(得分:4)

  

当我将类似数组的变量传递给函数时,每当我将其作为参数传递给其他函数时,它会为堆中的数组创建一个新空间,或者只是它在堆中使用相同的空间。只是传递参考

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 :(得分:1)

传递对象实质上是传递引用。例如,在函数之间传递数组时,您的数组将仅存在于内存中的一个位置。这是a runnable example说明的内容。

如果您愿意,可以在日常工作中重复使用相同的数组。请注意,对该数组所做的更改对于共享与该数组相同的引用的所有对象都是可见的。如果那不可取,则必须声明一个新数组。

答案 2 :(得分:1)

你可能会因为风格非常糟糕而且非常容易出错,并且未来的修改非常不安全。

以下是示例。

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?
    }

}

答案 3 :(得分:1)

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   
}