前段时间写java代码遇到一个值传递和引用传递的问题,回去查了下相关资料,对Java参数传递问题有了新的理解和认识,但是有个问题还是很困惑,那就是Java里到底是不是只有值传递,因为查阅资料的过程中,看到很多大牛说Java只有值传递,引用传递其实传递的是地址值,本身来说也是一种值传递,但是也有人说既有值传递,又有引用传递,姑且不去争论这个究竟,只是站在不同角度看待同一个问题所以得出了两个不同的观点,其实两个说法的原理是一样的,只要搞清楚Java参数传递的机制,叫什么传递也无所谓了,接下来跟大家分享一下我的一些粗浅的心得:
    1.什么是值传递
        传递实参的一个副本给形参,在被调用函数内对形参的修改不会影响到原来的实参。   
    public class Test {
    
    public static void main(String[] args) {
        int a=1;
        Test.changeNum(a);
        System.out.println("Main方法中的a = "+a);
    }
    public static void changeNum(int a){
        //do something
        a+=1;
        System.out.println("changeNum方法中的a = "+a);
    }
}运行结果是:
changeNum方法中的a = 2
Main方法中的a = 1
     可见实际参数的值并没有发生改变,改变的只是作为副本的形参。
     值传递重要特点:传递的是值的拷贝,传递后就没有任何联系了。
    2.什么是引用传递
        本质上还是值传递,只是把引用的值复制一份传递给形参,指向实参引用所指向的值,当对形参指向的内容操作时,就相当于对实参本身就行的操作。      
public class Test1 {
    public static void main(String[] args) {
        A a = new A();
        a.age=10;
        test1(a);
        System.out.println("Main方法里age = "+a.age);
    }
    public static void test1(A a){
        a.age=20;
        System.out.println("test1方法里age = "+a.age);
    }
}
class A{
    int age=0;
}运行结果如下:
test1方法里age = 20
Main方法里age = 20
 3. 引用传递的过程-内存分配示意图
    要想正确的理解java的引用传递,就必须了解java内存分配的过程,下面的内存分配示意图可以帮助我们理解这个过程:
    (1)运行开始,到第4行,Main方法里创建了一个类A的实例,内存分配示意图如下:
            main方法里的变量age→这是类A的一个实例a,此时age=0.
    (2)运行到5行,是修改A实例里age的值,运行后内存分配示意图如下:
            main方法里的变量age→这是类A的一个实例a,此时age=10.
    (3)运行到6行,是把main方法中的变量a所指向的内存空间地址,按引用传递给test1方法中的a变量。*注意:这两个变量a是完全不同的,不要被名称相同所蒙蔽。内存分配示意图如下:
            
    由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图:
            
    (4)运行到10行,为test1方法里的变量a指向的A实例的age进行赋值,然后形成新的内存示意图:
            
            此时A实例的age值的改变是由test1方法的形参改变引起的。
    (5)运行到11行,输出test1方法里的age=20.
    (6)运行到第7行,输出Main方法里的age=20.
    4. 再次理解引用传递
        将上述代码稍作修改:
    public class Test1 {
    public static void main(String[] args) {
        A a = new A();
        a.age=10;
        test1(a);
        System.out.println("Main方法里age = "+a.age);
    }
    public static void test1(A a){
        //此处增加了一行,将形式参数指向了一个新的A的实例
        a=new A();
        a.age=20;
        System.out.println("test1方法里age = "+a.age);
    }
}
class A{
    int age=0;
}
运行结果:
里age = 20
Main方法里age = 10
其实也不难理解,前面3部和上述相同,第4步开始如下:
(4)运行到11行,作为形参的a变量指向了新的A的实例。
    
(5)运行到12行,形参a变量的age重新赋值
    
    此时修改的是test1方法变量a的age,与main方法中的变量a所指的地址不同,所以main方法中的变量a的age值没有发生改变。
(6)运行到13行,输出test1方法里的age =20.
(7)运行到7行,输出Main方法里的age=10.
5.引用传递String类型的探讨
    我们都知道java里的String类型是一种引用类型,而不是值类型,虽然很多地方和值类型的特征相似,看下面这个例子:
public class Test {
    
    public static void main(String[] args) {
        String str="Hello";
        Test.changeStr(str);
        System.out.println("Main方法中的str = "+str);
    }
    public static void changeStr(String str){
        //do something
        str+=" World!";
        System.out.println("changeStr方法中的str = "+str);
    }
}输出结果:
changeStr方法中的str = Hello World!
Main方法中的str = Hello
那么为什么String类型的引用传递没有改变Main方法里的str的值呢?大家可以去深入了解下java里String类型的特性,答案就显而易见,这里就不做赘述了。以上是我的一点浅薄的见解,希望大家多多指教。