Java中参数传递方式(按值传递还是引用传递)

    |     2015年5月15日   |   Java面试题   |     0 条评论   |    1579

先看程序员都熟悉的值传递:把基本类型传进方法,方法里改的是副本,调用方变量不会变。Java 里对象参数同样是值传递——传的是引用的副本,不是把引用变量本身搬过去。

所以:方法里能改对象内部状态,却改不了调用方那个引用变量指向谁。下面用两段代码和两张原图说明。

一、基本类型:传的是存储单元里的内容

public static void changeValue(int x) {
    x = x * 2;
}

int num = 5;
System.out.println(num);
changeValue(num);
System.out.println(num);

调用前后 num 都是 5。过程如图:

fe0d1504-e8e6-3e01-a141-6987030fdeed

num 传给 changeValue 时,是把 num 那个存储单元里的值 5 拷给方法里的 x,x 另有自己的存储单元。之后对 x 的操作与 num 无关。值传递的精髓是:传递存储单元中的内容,而不是地址把柄本身。

二、对象参数:仍然是值传递

class Person {
    public static String name = "Jack";
}

public static void changeName(Person p) {
    p.name = "Rose";
}

public static void main(String[] args) {
    Person person = new Person();
    System.out.println(person.name);
    changeName(person);
    System.out.println(person.name);
}

第一次打印 Jack,第二次 Rose。很多人以为方法收到的是引用本身,其实收到的是引用的副本。

http://www.cnblogs.com/clara/archive/2011/09/17/2179493.html 写道:Java 只有值传递。对象实例作为参数时,参数的值是该对象引用的一个副本,指向同一个对象。对象内容可以在被调方法里改变,但调用方的引用(不是副本)永远不会被改掉。

a9f38c27-261d-3f39-8384-16025b2b9338

new Person() 实际涉及两块:堆里的实体对象,和栈里的引用变量 person。图中左侧堆、红色框是实体、起始地址 000012;右侧栈里 person 存的正是 000012。

调用 changeName(person) 时,person 把自己存储单元里的内容(实体地址)传给方法参数 p。此后对 p 的操作针对 p 自己的那一格,与 person 那一格无关——这和基本类型把 5 拷走是同一件事,所以仍叫值传递,不是引用传递。

对象内部能变,是因为 p 里存着实体地址,p 也指向同一块堆内存,于是能改属性。这正是误以为“引用传递”的原因。

传递什么 方法里改副本 调用方看得到的效果
基本类型的值 改的是方法里的 x 调用方 num 不变
对象引用的副本(地址值) 改 p 指向谁,不影响 person 改 p 所指对象的字段,调用方能看见

一句话总结:Java 只有值传递:基本类型拷数值,对象拷引用副本;能改对象内容,改不了调用方那个引用变量。

转载请注明来源:Java中参数传递方式(按值传递还是引用传递)
本文链接地址:https://ai.zhousir.top/?p=656
回复 取消