use*_*476 1 java arguments pass-by-reference
我偶然发现了Java的一个非常令人费解的功能(?).
似乎使用"new"关键字替换方法参数将该对象转移到不同的范围:
import java.util.ArrayList;
public class Puzzle {
public static void main(String[] args) {
ArrayList<Integer> outer = new ArrayList<Integer>();
outer.add(17);
Puzzle.change(outer);
outer.add(6);
System.out.println(outer);
// excpected output:
// [23]
// [23, 6]
//
// actual output:
// [23]
// [17, 7, 6]
}
public static void change(ArrayList<Integer> inner) {
inner.add(7);
inner = new ArrayList<Integer>();
inner.add(23);
System.out.println(inner);
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释这种奇怪吗?我注意到了与分配相同的行为.
这是Java初学者的经典之旅.部分问题在于我们缺乏识别这一点的共同语言.参数是按值传递的吗?对象通过引用传递?根据您与谁交谈,对于通过值传递的单词会有不同的反应并通过引用传递,即使每个人都想说同样的事情.
可视化的方法是理解java变量可以是两件事之一.它可以包含基元或对象的引用.将该引用视为指向内存中某个位置的数字.它不是C++中的指针,意味着它不指向特定的内存位置,它更像是一个句柄,因为它允许JVM查找可以找到对象的特定内存位置.但你可以这样形象化它:
ArrayList<Integer> outer = @1234; //The first reference where the ArrayList was created.
Run Code Online (Sandbox Code Playgroud)
然后使用以下参数调用inner:
Puzzle.change(@1234);
Run Code Online (Sandbox Code Playgroud)
请注意,如果不传递外部变量,则传递@ 1234的值.通过作为方法的参数,不能以任何方式更改外部.当我们说通过价值时,这就是我们的意思.传递该值,但它与外部变量断开连接.
内部拼图:
public static void change(ArrayList<Integer> inner) { // a new reference inner is created.
//inner starts out as @1234
inner.add(7);
//now inner becomes @5678
inner = new ArrayList<Integer>();
//The object @5678 is changed.
inner.add(23);
//And printed.
System.out.println(inner);
}
Run Code Online (Sandbox Code Playgroud)
但是外部仍然指向@ 1234,因为方法不能改变它,它从来没有外部变量,它只是有它的内容.但是,由于更改方法是在引用@ 1234时开始的,因此该方法确实可以更改该位置的对象,并且对@ 1234的任何其他引用都可以看到结果.
更改方法完成后,没有任何内容引用对象@ 5678,因此它有资格进行垃圾回收.
这是初学者的经典java问题之一.
内部参数按值传递(对于非基本对象,它是引用).如果您对它采取行动,它会影响与外部代码中相同的对象,因此您可以看到外部方法中的影响.
如果用新对象替换对象,它就不一样了.当您处理新的时,您不会更改上一个,并且您没有看到外部方法的影响.
更新:对不起引起很多评论的词汇错误.我现在纠正了我的回答.我相信这一点,但现在更清楚了.
在java中,您可以将所有变量视为指向真实对象的指针.
这是怎么回事:
| 归档时间: |
|
| 查看次数: |
984 次 |
| 最近记录: |