关于java引用传递的疑问?

颖辉小居 发布于 2017/06/05 10:04
阅读 1K+
收藏 2

请看下面的代码:

package yinyong;

public class Main {
	public static void main(String[] args) {
		A a = new A(null, "", "", "");
		System.out.println(a);
		function(a);
		System.out.println(a);
	}

	static void function(A a) {
		A a2 = new A("a", "b", "c", "d");
		a = a2;//标注1
		//a.setA(a2.getA());//标注2
	}
}

 A.java

package yinyong;

public class A {
	String a;
	String b;
	String c;
	String d;

	public A() {
		super();
	}

	public A(String a, String b, String c, String d) {
		super();
		this.a = a;
		this.b = b;
		this.c = c;
		this.d = d;
	}

	public String getA() {
		return a;
	}

	public void setA(String a) {
		this.a = a;
	}

	public String getB() {
		return b;
	}

	public void setB(String b) {
		this.b = b;
	}

	public String getC() {
		return c;
	}

	public void setC(String c) {
		this.c = c;
	}

	public String getD() {
		return d;
	}

	public void setD(String d) {
		this.d = d;
	}

	@Override
	public String toString() {
		return "A [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + "]";
	}

}

运行结果

a = a2;//标注1

A [a=null, b=, c=, d=]
A [a=null, b=, c=, d=]

main方法中a的内容没有改变

a.setA(a2.getA());//标注2

A [a=null, b=, c=, d=]
A [a=a, b=, c=, d=]

main方法中a的内容有改变

为什么一个变化一个不变化,

java中除了基本类型和String才是值传递,其他所有类型(包括 new String("xx")方式创建的字符串)都是引用传递。

好像和这个说法不符。

另外如果把function()中的内容直接写到main中a就都是变化的

加载中
1
chaozhang
chaozhang
// Java只有值传递
a = a2;//a2和a指向同一块值存储,没有改变原有a对象,作用域为方法
a.setA(a2.getA());//通过自定义属性更改方法改变了a对象,打印出来的hash变化了
// toString源码
public String toString{
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

 

颖辉小居
颖辉小居
我有点明白了,就是当方法中的a还没有=a2时,它和外部的a指向的同一个对象,这是它们唯一的联系。当a=a2以后这个a已经指向新的地址和外部的a没有任何关系了。虽然方法中的a已经改变了,可是外部的a还是指向原来的对象。
月生无界
月生无界
java确实只有值传递,除了基本类型,你看似引用传递的对象,其实传递的是引用的地址值,我是搬运工http://www.cnblogs.com/coderising/p/5697986.html
颖辉小居
颖辉小居
a=a2 这个应该使a指向了a2的物理地址吧,和本来a的物理地址不同,我debug的时候可以看到a的内容已经变了,但运行完这个function在main中a是没有变化了,就像您说的作用域是方法内,请问为什么会这样呢?
1
乌龟壳
乌龟壳

java的引用不是变量名的引用,而是说变量存储的内容是指针。

1
槽卤

因为在main当中的a一直都没变,一直指向a对象,function中的a刚开始指向a对象,后来指向a2对象。

1
J
Jinzty

方法变量拷贝了指针,你方法里面改变指针变量并不能影响方法外原来的指针

J
Jinzty
回复 @颖辉小居 : 对的,拷贝的是指针,java里一般叫引用
颖辉小居
颖辉小居
我有点明白了,就是当方法中的a还没有=a2时,它和外部的a指向的同一个对象,这是它们唯一的联系。当a=a2以后这个a已经指向新的地址和外部的a没有任何关系了。虽然方法中的a已经改变了,可是外部的a还是指向原来的对象。
1
城头的土人
城头的土人

http://blog.csdn.net/fbysss/article/details/3082949,一篇老文章,但对Java的参数传递解释得很清楚。function 中的a是传递进去的参数的一个副本a',因此对这个副本a‘的操作不影响函数体外部的参数 。

颖辉小居
颖辉小居
这篇文章我以前看过,我这里的A是自定义的,按照文章说的明显是引用传递,我在方法里使用两种方式修改,第一种直接改了引用地址,外部没有影响。第二种使用set方法改变属性,外部有变化。按照这篇文章我觉得都应该变化。
1
kailuncen
kailuncen

一楼的补充:

“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。

运行结果是

A{field1='null', field2='', field3='', filed4=''}
A{field1='null', field2='', field3='', filed4=''}

如果是基本类型是值,则是值的拷贝。

如果是传递的是类,则是传递的引用,即传递的地址。

在function里的a 和 main函数里的a 不是同一个a,他们只是指向了同样的地址。

在function里,a指向的地址被改变了,但main函数里指向的地址没变。

所以回到主函数后,main函数中a指向的地址不变。我改动了代码,把function里面的a返回了回来

结果:

 

希望采纳。

 

1
一只小桃子
一只小桃子

进入一个新方法。

为这个方法创建一个桢,压入栈。

这个栈桢的局部变量表里是对a1的引用。

将局部变量表a1的引用修改为a2.

桢执行完毕,弹出栈,回到上一个方法。

上一个方法中的a1是自己桢中局部变量表里的引用。

看字节码就知道了

一只小桃子
一只小桃子
扯那么多概率有屁用,学习jvm执行过程,看java字节码才是王道
0
programming_monk
programming_monk

传参,可以看做是副本传递,就是将参数复制一份传进方法(基本类型传值的副本,引用类型传地址的副本),最好你再了解下形参和实参概念。

此处你操作的是引用类型A a ,a的成员变量也是引用类型 String:

a=a2:创建一个引用变量a2,将 a2的地址赋给了形参a(方法中的形参a,方法结束释放资源,不影响main中的变量),所以a输出前后没有改变;

a.setA(a2.getA()):执行该操作是将a2地址指向的值取出来存到a地址指向的内存,a对象地址没有改变,但是地址指向内存中的值变了.

关于你说的最后一条:另外如果把function()中的内容直接写到main中a就都是变化的

放在方法中就是操作同一个对象,肯定值改变啊!

0
MZHS
MZHS

你是奇怪为什么打印出来的东西不一样吗?

0
烟头
烟头

java都是值传递  引用传递是传递地址

烟头
烟头
回复 @颖辉小居 : c的指针是引用传递啊 传递的是地址的地址
颖辉小居
颖辉小居
那这样说,什么语言都不会有引用传递了吧,因为都能说成是地址的值传递
返回顶部
顶部