Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在方法中重复使用变量安全吗?_Java_Jakarta Ee - Fatal编程技术网

Java 在方法中重复使用变量安全吗?

Java 在方法中重复使用变量安全吗?,java,jakarta-ee,Java,Jakarta Ee,我有一个字符串类型的数组,我想在方法中重用它 我需要将其传递给一个函数,该函数返回传递的数组元素的子集。要从函数中捕获返回的数组,我应该声明一个新的字符串数组,还是可以安全地重新使用保存未筛选数组的同一数组来保存已筛选数组 还要澄清的是,当我将一个类似数组的变量传递给函数时,每次我将其作为参数传递给其他函数时,它是否会在堆中为数组创建一个新的空间,还是只是它在堆中使用相同的空间&只是传递引用?我猜在数组的情况下,它只传递引用,但在简单变量的情况下,它在堆栈上分配新的空间,对吗 编辑:感谢你们所有

我有一个字符串类型的数组,我想在方法中重用它

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

还要澄清的是,当我将一个类似数组的变量传递给函数时,每次我将其作为参数传递给其他函数时,它是否会在堆中为数组创建一个新的空间,还是只是它在堆中使用相同的空间&只是传递引用?我猜在数组的情况下,它只传递引用,但在简单变量的情况下,它在堆栈上分配新的空间,对吗

编辑:感谢你们所有人的精彩回答和解释


还请澄清,如果我重复使用数组,是否需要在结束数组子集时的位置设置null?(实际上,我的数组的子集不是直接从数组中计算出来的,而是一些其他的计算,因此我需要手动设置空值,否则列表中较旧的元素将可见,对不对??

传递对象本质上就是传递引用。例如,在函数之间传递数组时,数组将只存在于内存中的一个位置。下面是一个例子


如果愿意,可以在例程中重用相同的数组。请注意,对该数组所做的更改将对共享对该数组的相同引用的所有对象可见。如果不需要这样做,那么必须声明一个新数组

您可能会发现,这是一种非常糟糕的样式,非常容易出错,并且对于将来的修改非常不安全

这是一个例子

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

}
,当我将类似数组的变量传递给 一个函数会创建一个新的空间 对于堆中的数组,每次 将其作为参数传递给其他用户 函数或只是它使用相同的 堆中的空间&只经过 推荐人

更新:基本示例

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   
}
当我将一个类似于数组的变量传递给函数时,每次我将其作为参数传递给其他函数时,它是否会在堆中为数组创建一个新的空间,或者只是它在堆中使用相同的空间&只是传递引用

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完全是按值传递的,所以引用的值会传递给函数),它仍然指向与原始引用相同的内存

由于引用是通过值传递到函数中的,因此函数无法更改调用代码的引用:

您会注意到,这正是原语的处理方式:

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
)可能更合适,但这是一个风格问题,取决于具体情况。

您的观点是正确的!但是,我的函数太小,充满了注释,无法记住东西,如果它能帮助我节省一些堆空间,那么它可能值得吗?因为字符串数组空间也不便宜…简单的数据类型如int/char呢,当我们将它们传递给一个方法时,我猜它们会再次复制到堆栈中,甚至在这种情况下只传递一个引用??没有简单的基元类型(int-char)按值传递,值会复制到被调用的函数参数中,但是每个都有自己的值,更改函数参数中的值不会影响传递的原始值。@Marcos:原语被复制。有关详细信息,请参阅我的答案。还请澄清,如果我正在重用数组,是否需要在结束数组子集时的位置设置null?(实际上,我的数组的子集不是直接从数组中计算出来的,而是其他一些计算,因此我需要手动设置null,否则列表中较旧的元素将可见,对不对??)@Marcos:这将完全取决于过滤函数及其处理数组的方式。大多数过滤函数都会返回一个新数组,其中只包含与过滤器匹配的元素,因此无需执行任何操作。在任何情况下,在Java中,我们(通常)不使用
null
来标记数组的结尾,这更像是C语言中的一个习惯用法。如果合适的话,您可以这样做,但通常不会。我自己正在定义数组的过滤函数,因此我肯定需要标记数组的结尾,否则它将与旧数组合并?????@Marcos:同样,在Java世界中,使用
null
标记数组的结尾是不寻常的,但是如果您愿意,您可以这样做。这可能会让事情变得更清楚一些,我以几种不同的方式编写了一个过滤数组的示例:请注意,没有一种过滤方法是线程安全的,如果您需要的话,您必须采取适当的保护措施。我并不是说这是唯一的方法。只是普通的。
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"
// 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
}