不是危言耸听,这道题很多人都做错,其中很多是资深开发人员。
请问下面程序运行后输出什么:
A、老唐 B、令狐冲 C、杨过 D、郭靖
public class Test {
public static void main(String[] args) throws Exception {
Member me = new Member();
me.setId(1);
me.setName("老唐");
chuanyue(me);
System.out.println(me);
}
// 方法chuanyue,即:穿越
public static void chuanyue(Member member) {
member.setId(1001);
member.setName("令狐冲");
Member member_other = new Member();
member_other.setId(1002);
member_other.setName("杨过");
member = member_other;
member.setId(1003);
member.setName("郭靖");
}
}
class Member {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Member [id=" + id + ", name=" + name + "]";
}
}
答案是: B、令狐冲
你答对了吗?
分析:
当我们调用chuanyue(me)时,函数内部会做一个隐式操作:member=me;
关键就在member=me这里:在java中,给对象赋值是传递的对象地址(指针变量)!
因此member=me就让member和me指向了同一个对象,操作member相当于操作me。
当执行
member.setId(1001);
member.setName("令狐冲");
相当于执行
me.setId(1001);
me.setName("令狐冲");
就是在这里,me对象变成了令狐冲了
接下来创建了一个对象member_other,然后调用
member = member_other;
这一句让member和member_other指向了同一个对象,操作member相当于操作member_other
所以这时执行
member.setId(1003);
member.setName("郭靖");
相当于执行
member_other.setId(1003);
member_other.setName("郭靖");
然后方法结束,局部变量member,member_other被销毁
最终me就是令狐冲
不啰嗦,看下图理解:
指针的指针
我问有些回答错误的人,他们大多数答案是 D、郭靖。
其关键是认为在方法内部调用member = member_other;
时,会让me也指向member_other。简单的说,他们认为member的一切改变都会影响me。
这实际上理解的最大误区就在于:认为方法形参向实参传递时,是传递了指针的指针。
不过,在有些情况下如果你想做到方法形参的任何改变,都会影响实参,那确实就必须要传递指针的指针。
方法参数传递指针的指针的情况
见图解: