Java传引用问题

 使用Java调用方法时,可以传值,也可以传引用。下面说说两者的区别:

1.传值

传值中的“值”类型是指java的8大基本类型(基础知识,不知道请自行谷歌)。使用java传值是把实参的值传递给形参,但是对形参所做的任何改变都对实参没有影响。例如以下代码:
public Class Demo{

        public static void test(int x){
            x++;
            System.out.println("方法内,x == "+x);
        }
        
        public static void main(String[] args){
            
                int a = 3;
                Demo.test(a);
                System.out.println("方法外,a == "+a);
                
        }        
        
}
public Class Demo{

        public static void test(int x){
            x++;
            System.out.println("方法内,x == "+x);
        }
        
        public static void main(String[] args){
            
                int a = 3;
                Demo.test(a);
                System.out.println("方法外,a == "+a);
                
        }        
        
}

运行结果:
方法内,x == 4
方法外,a == 3

解析:尽管x的值已经加1变成了4,但是当test()方法执行结束后,x就被销毁了,其值不能传回给实参a。学过C的应该知道:向方法中传值是单向的,只能由形参传给实参,不能反过来。在java中亦如此。所以改变形参的值对实参没有影响。

2.传引用

A.在方法内改变引用的指向

如下代码:
public class Test {

    public static void main(String[] args) {
        Integer a = 20;
        System.out.println("修改前:" + a);
        TestStudent.modify(a, 900);
        System.out.println("修改后:" + a);
    }


    public static <T> void modify(T a, T b) {
        a = b;
    }
    
}
public class Test {

    public static void main(String[] args) {
        Integer a = 20;
        System.out.println("修改前:" + a);
        TestStudent.modify(a, 900);
        System.out.println("修改后:" + a);
    }


    public static <T> void modify(T a, T b) {
        a = b;
    }
    
}

运行结果:
修改前:20
修改后:20

虽然在modify()方法中将a指向了b,但是在方法结束后,modify()方法内的a和b都被销毁了,对main()方法内的实参没有影响。modify()方法只是改变了形参的指向,并未改变实参的指向。如图:

java 传引用 map_调用方法

main()方法中的a与modify()方法中的a都指向堆中的同一个对象,但是改变modify()方法中的a的指向对main()方法中的a的指向并没有影响,所以一切都是白费的。

B.在方法内改变引用的对象的属性

倘若在被调用方法内部改变了形参变量引用的对象的属性,会对实参变量引用的对象产生影响。因为形参变量和实参变量引用的是堆中的同一个对象。看下面一个例子:

Student类:
public class Student {

    public Student() {
        
    }

    public Student(String name, String sex, String tel) {
        super();
        this.name = name;
        this.sex = sex;
        this.tel = tel;
    }

    private String name;
    private String sex;
    private String tel;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getTel() {
        return tel;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", sex=" + sex + ", tel=" + tel + "]";
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

}
public class Student {

    public Student() {
        
    }

    public Student(String name, String sex, String tel) {
        super();
        this.name = name;
        this.sex = sex;
        this.tel = tel;
    }

    private String name;
    private String sex;
    private String tel;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getTel() {
        return tel;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", sex=" + sex + ", tel=" + tel + "]";
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

}
Test类:
public class TestStudent {

    public static void main(String[] args) {

        Student s = new Student("Obama", "Male", "10256905");
        Student student = new Student("Bill", "Female", "10256905");

        System.out.println("      修改属性");
        System.out.println("修改前:" + s);
        TestStudent.test(s, "Jeff");
        System.out.println("修改后:" + s);

        System.out.println("\n      修改指向");
        System.out.println("\n修改前:" + s);
        TestStudent.modify(s, student);
        System.out.println("修改后:" + s);

    }

    public static void test(Student s, String name) {

        s.setName(name);

    }

    public static <T> void modify(T a, T b) {

        a = b;
    }
}
public class TestStudent {

    public static void main(String[] args) {

        Student s = new Student("Obama", "Male", "10256905");
        Student student = new Student("Bill", "Female", "10256905");

        System.out.println("      修改属性");
        System.out.println("修改前:" + s);
        TestStudent.test(s, "Jeff");
        System.out.println("修改后:" + s);

        System.out.println("\n      修改指向");
        System.out.println("\n修改前:" + s);
        TestStudent.modify(s, student);
        System.out.println("修改后:" + s);

    }

    public static void test(Student s, String name) {

        s.setName(name);

    }

    public static <T> void modify(T a, T b) {

        a = b;
    }
}

运行结果:

修改属性

修改前:Student [name=Obama, sex=Male, tel=10256905]
修改后:Student [name=Jeff, sex=Male, tel=10256905]

修改指向

修改前:Student [name=Jeff, sex=Male, tel=10256905]
修改后:Student [name=Jeff, sex=Male, tel=10256905]

从运行结果可以看出,调用方法改变形参的指向对实参并没有影响。但是如果试图改变形参所指向的对象的属性会对实参所指向的对象产生影响。
 
    综上所述:只有在调用方法内改变引用变量所引用的对象的属性才会对调用方法中的对象产生影响。因为形参变量和实参变量指向堆中的同一个对象。
    ps:第一次写技术博客,有不足处还望大家指出来,以后我会慢慢改进。谢谢大家的支持。