首先,Java中并不存在指针,但有类似的现象,叫“引用传递”。
一部分人觉得java中存在【引用传递】和【值传递】,而也有一部分人认为java中只存在【值传递】。他们表达的意思是一样的,却是从两个方面来表达。
首先java中的确存在两种情况。下面来看一个例子;
public class Test {
public static void change(int a){
a=50;
}
public static void main(String[] args) {
int a=10;
System.out.println(a);
change(a);
System.out.println(a);
}
}
输出:10,10
可见change方法并没有改变main中的a的值。
这里传递到change中的a
是一个拷贝,对原来的值不产生影响。
再看:
public class Test3 {
public static void change(int []a){
a[0]=50;
}
public static void main(String[] args) {
int[] a={10,20};
System.out.println(a[0]);
change(a);
System.out.println(a[0]);
}
}
输出:10,50;
可见这里的change方法改变了main中的a,
这里传递到change中的a
是一个地址的值,指向原来的值。
<br />
深入
我们来看下面的例子:
作者:Intopass
链接:https://www.zhihu.com/question/31203609/answer/50992895
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
第一个例子:基本类型
void foo(int value) {
value = 100;
}
foo(num); // num 没有被改变
第二个例子:没有提供改变自身方法的引用类型
void foo(String text) {
text = "windows";
}
foo(str); // str 也没有被改变,也因为每一个"xxx"都是一个新的对象
第三个例子:提供了改变自身方法的引用类型
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
builder.append("4");
}
foo(sb); // sb 被改变了,变成了"iphone4"。
第四个例子:提供了改变自身方法的引用类型,但是不使用,而是使用赋值运算符。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
builder = new StringBuilder("ipad");
}
foo(sb); // sb 没有被改变,还是 "iphone"。
这里有些人可能对图四难以理解,为什么foo方法中对传入的sb做了赋值,但是sb还是没有改变呢?
那我们再来看看下面的例子和相应的内存模型:
public static void main(String[] args) {
Demo d1 = new Demo();
fun(d1);
);
}
public void fun(Demo d2){
xxxx;
}
这里我们发现,当调用fun
方法的时候,栈内存中出现了d2
值,指向了d1
指向的空间。
这也就解释了上面第四个例子:当调用foo
方法传入d1
时,实际上是在栈内存中新增了d2
值,同时d2
指向d1
指向的堆内存空间。当foo
方法内部进行新的【赋值】操作时,实际上改变了的是d2
的指向,并不会改变d1的值。
这里我们需要注意的一点是d2的赋值是改变其指向的位置。而不是改变指向位置的值。