1 回答
TA贡献1998条经验 获得超6个赞
这个问题要分具体的情况的,我下面列举了三种情况,基本上就都包括了,剩下都可以通过这三种情况类似,先看一下我写了一段测试结果用的代码,先看结果,之后我再解释原因
public class Student { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }public class TestRef { public static void main(String[] args) { List<Student> list = new ArrayList<>(); list.add(new Student("zhang",12)); list.add(new Student("liu",13)); System.out.println("list中是普通对象时,修改前"); System.out.println(list); Student stu = list.get(0); stu.setAge(22); System.out.println("list中是普通对象时,修改后"); System.out.println(list); List<Integer> list1 = new ArrayList<>(); list1.add(1); list1.add(2); System.out.println("list1中装入基本类型时,修改前"); System.out.println(list1); Integer a = list1.get(0); a = new Integer(11); System.out.println("list1中装入基本类型时,修改后"); System.out.println(list1); List<String> list2 = new ArrayList<>(); list2.add("abc"); list2.add("def"); System.out.println("list2中装入String时,修改前"); System.out.println(list2); String s = list2.get(0); s = new String("abc_abc"); System.out.println("list2中装入String时,修改后"); System.out.println(list2); }} |
下面是运行的结果:
list中是普通对象时,修改前[Student [name=zhang, age=12], Student [name=liu, age=13]]list中是普通对象时,修改后[Student [name=zhang, age=22], Student [name=liu, age=13]]list1中装入基本类型时,修改前[1, 2]list1中装入基本类型时,修改后[1, 2]list2中装入String时,修改前[abc, def]list2中装入String时,修改后[abc, def] |
通过上面的例子我们就会发现,我们在修改Student实例中的年龄是可以修改的,但是在修改基本类型(int,long,short,byte,char,float,double,boolean)和String的时候是不变的。这个是直观的感受,真是是后面这一半是正确的。
我写Student这个类的目的就是为了来描述我们自己定义的类会不会变,通过上面的例子我们发现变了,那么什么情况下不变呢,看下面这段代码:
List<Student> list = new ArrayList<>(); list.add(new Student("zhang",12)); list.add(new Student("liu",13)); System.out.println("list中是普通对象时,修改前"); System.out.println(list); Student stu = list.get(0); //stu.setAge(22); stu = new Student("song",24); System.out.println("list中是普通对象时,修改后"); System.out.println(list); |
这段代码是没有修改list中的内容,其实到这里所有的情况就都包括了,很简单,在Java中传递引用,大家经常会把它理解为传递C语言中的指针,其实不然,你更应该把他理解为C语言中的传递值,这样就容易解释一些现象。
以Student这段代码为例,list.get(0)拿到的是第一个Student实例的值,当我们直接修改这个实例的时候,是不会影响到list中的内容的,如
Student stu = list.get(0);stu = new Student("song",24); |
这种是没有影响的,但是我们修改返回的这个实例中的属性的时候的,也就是修改Student中的年龄,姓名等的时候,这个时候是会改变list中的内容的(list中Student的引用的值没变,但是引用所指向堆中对象具体的属性改变了)。
也就是下面这种形式会改变的:
Student stu = list.get(0);stu.setAge(22); |
通过这种方式,我们就可以理解基本类型和String的时候为什么不会变了。
添加回答
举报
