首先我们来看一段代码:
package my.java.test; public class Parameter { static class Year { private int year; public int getYear() { return year; } public void setYear(int year) { this.year = year; } public Year(int year) { this.year = year; } } static void change_1(Year year) { year.setYear(2019); } static void change_2(Year year) { year = new Year(2020); } public static void main(String[] args) { Year thisYear = new Year(2018); System.out.println(thisYear.getYear()); change_1(thisYear); System.out.println(thisYear.getYear()); change_2(thisYear); System.out.println(thisYear.getYear()); } }
运行结果:
2018
2019
2019
Process finished with exit code 0
可能会有人纳闷了,为什么change_2不起作用类,我们传递的不是引用类型吗,不是会指向同一个对象吗,按理说应该也会改变的啊,当你看到这里的时候,你不妨看看我对java中参数的传递和内存分配的理解:
1,在java中,有两种类型的变量,一种是基本类型,一种是引用类型,我们都知道,基本类型是值的传递(就是把字面值复制了一次),而引用类型是引用的传递,所谓传递引用,就是导致让方法的形参和调用方法时传递的实参指向了同一个对象.
2,如果你知道在java中,方法的参数传递无论是基本类型还是引用类型,都是用过内存的复制来实现的,那么你就可以理解什么的change_2,没有效果了,首先我们来说一下,什么事所谓的内存复制.当我们调用到change_1时,会给其传入一个实参,然后在change_1的方法定义处:
static void change_1(Year year)
括号内部申请了一个变量year,这是个局部变量,此时jvm会帮你把实参中你传入的引用复制给这个新申请的引用,所以也就是说,这个括号内部定义的引用变量和你调用方法时传入的参数指向的是同一个对象,但是他们是另个没有任何联系的引用变量,只是他们指向的是同一片内存地址,如果你操作任何一个,都会导致对象的值的改变.
但是如果你此时让这个新申请的引用指向一个新的对象,也就是change_2,那么这个应用就会重新指向一个新的内存地址,那么当你调用change_2方法导致change_2的形参指向的那片内存地址(就是你传入的引用说指向的对象)根本还没使用,就让形参指向了一个新的对象,那么这个形参和你传入的实参已经没有任何关系了,他们分别指向了不同的对象,所以这也就可以解释为什么change_2没有效果,而且在change_2的形参定义处会显示灰色(即未使用)的原因了(就是因为还未使用原来指向的那片内存地址的对象,就重新指向了一个新的对象).