java形参、实参、值传递、引用传递

工作中,发现大多数人对值传递,引用传递理解不深,下面写一遍文章详细聊聊。

一、形参

形参:用来接收调用方法时传递的参数,只有在被调用时才分配内存,一旦调用结束,就释放内存空间。因此仅在方法内有效。

public void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

这里a,b就是形参,方法结束时,在栈空间就会被销毁。

二、实参

调用上面方法swap(6, 8); 其中6 8就是实参。

三、值传递和引用传递

  • 值传递:方法调用时,实际参数将它的值传递给形式参数,函数就收到的是原始值的副本,此时内存中存在两个相同的基本类型,若方法中对形参执行处理操作,并不会影响实际参数的值。
  • 引用传递:方法调用时,实际参数的引用(指内存地址,不是参数的值)被传递给方法中相应的形式参数,函数接受到的是原始值的内存地址,在方法中,形参和实参的内容(地址)相同,方法中对形参的处理会影响实参的值。

public class People {

    private String name;
    private String age;

    public People(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}


public class Base1 {
    
    public static void main(String[] args) {

        int a = 10;
        // 按值传递
        test1(a);
        System.out.println("main a==" + a);
        People p = new People("rose", "18");
        // 按引用传递
        test2(p);
        System.out.println("main name==" + p.getName() +", age==" + p.getAge());
    
    }

    public static void test1(int a) {
        a = 20;
        System.out.println("test1 a==" + a);
    }

    public static void test2(People p) {
        p.setName("jack");
        p.setAge("19");
        System.out.println("test2 name==" + p.getName() +", age==" + p.getAge());
    }
}

输出结果:
test1 a==20
main a==10
test2 name==jack, age==19
main name==jack, age==19

结论:

  • 形参为基本类型时,对形参的处理不会影响实参。
  • 形参为应用类型时,对形参的处理会影响实参。
  • String、Integer、Double等immutable类型,因为本身没有提供修改函数的操作,每次操作都是生成一个新对象,所以要特殊对待,可以理解为值传递,形参操作不会影响实参对象。

四、java对象及引用

以上面的People为例,构建一个对象:People p1 = new People("jack", "19");
其实这个对象包含四个动作。

  • 右边的new People,是以People类为模板,在堆空间创建一个People类对象。
  • 末尾的("jack", "19"),指的是对象创建后,调用的构造函数,对刚生成的对象进行初始化。
  • 左边的People p1创建了一个People类引用变量,所谓People类引用,就是以后可以用来指向People对象的引用。
  • = 操作符使对象引用指向刚创建的People对象。
People p1;
p1 = new People("jack", "19");
上面两条语句等价于 People p1 = new People("jack", "19");

这样看就很明白,一个是对象应用变量,一个是对象实体。
如果只执行第一条,还没执行第二条此时创建的p1还没指向任何一个对象,它的值是null。

再来一句:
People p2;
p2 = p1;
这里发生了复制行为,对象本身没有复制,被复制的只是对象的引用。结果是p2也指向了p1的对象。

再来一句:
p2 = new People("rose", "18");
此时p2指向了第二个对象,此时得出结论:
一个对象引用可以指向0个或者1个对象。
一个对象可以有N个引用指向它。

再来一句:
p1 = p2;
此时p1指向p2这个对象,至于之前的p1这个对象,它已成为垃圾回收机制的处理对象。


四、java中方法参数的引用传递

“当一个对象被当作参数传递到一个方法”,这就是所谓的引用传递。

public class Base2 {
    public static void main(String[] args) {
        People p = new People("jordon","23");
//        changePeople1(p);
        changePeople2(p);
        System.out.println(p.getName() + "===" + p.getAge());
    }

    public static void changePeople1(People p) {
        p.setName("kobe");
        p.setAge("24");
    }

    public static void changePeople2(People p) {
        p.setName("kobe");
        p.setAge("24");

        p = new People("james", "24");
    }
}

以上代码调用changePeople1和changePeople2都是输出
kobe===24
我们来分析下为什么了??

posted @ 2019-09-23 16:59  wudiffs  阅读(5004)  评论(0编辑  收藏  举报