Java是值传递还是引用传递

119 阅读2分钟

前言

许久未曾写文了,今天决定水一篇

——南方

证明

形参/实参

  • 形参:用于定义函数/方法,接收实参,不需要有确定的值
  • 实参:用于传递给函数/方法的参数,必须有确定的值
public static void main(String[] args) {
        String a = "b";
        //这里的a就是实参
        print(a);
    }

    //这里的s参数就是形参
    public static void print(String s){
        System.out.println(s);
    }


值传递/引用传递

  • 值传递 :方法接收的是实参值的拷贝,会创建副本
  • 引用传递 :方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本

证明过程

使用基本类型参数

    public static void main(String[] args) {
        String a = "a";
        String b = "b";
        print(a, b);
        System.out.println("a:" + a); //a:a
        System.out.println("b:" + b); //b:b
    }

    public static void print(String c, String d) {
        String e = c;
        c = d;
        d = e;
        System.out.println("c:" + c); //c:b
        System.out.println("d:" + d); //d:a
    }

上述代码很简单,结果呢,很明确,经过print()方法的执行,丝毫未影响到 a,b本身的值,因为c,d的值只是从a,b那里复制过来的,原来的还是原来的,复制品的修改不影响原品的数据

使用引用类型

public class Dog {
    String name;

    Dog(String name) {
        this.name = name;
    }

    String getName() {
        return this.name;
    }

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

    String getObjectAddress() {
        return super.toString();
    }
}


public static void main(String[] args) {
	Dog dog = new Dog("A");
	System.out.println(dog.getObjectAddress()); //Dog@15db9742
	func(dog);
	System.out.println(dog.getObjectAddress()); //Dog@15db9742
	System.out.println(dog.getName()); // B
}
private static void func(Dog dog) {
	System.out.println(dog.getObjectAddress());//Dog@15db9742
	dog.setName("B");
	System.out.println(dog.getObjectAddress());//Dog@15db9742
}

此时就会有很多人疑惑了,为啥在这里值发生了改变,其实原因很简单,它们是引用的同一个对象

再次证明

public class Dog {
    String name;

    Dog(String name) {
        this.name = name;
    }

    String getName() {
        return this.name;
    }

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

    String getObjectAddress() {
        return super.toString();
    }
}


public static void main(String[] args) {
        Dog dog = new Dog("A");
        System.out.println(dog.getObjectAddress()); // Dog@15db9742
        func(dog);
        System.out.println(dog.getObjectAddress()); // Dog@15db9742
        System.out.println(dog.getName()); // A
    }
    private static void func(Dog dog) {
        System.out.println(dog.getObjectAddress()); // Dog@15db9742
        dog = new Dog("B");
        System.out.println(dog.getObjectAddress()); // Dog@6d06d69c
        System.out.println(dog.getName()); // B
    }

在上面⽅法中将指针引⽤了其它对象,那么此时⽅法⾥和⽅法外的两个指针指向了不同的对象,在⼀个 指针改变其所指向对象的内容对另⼀个指针所指向的对象没有影响

总结

Java 中将实参传递给方法的方式是:值传递

  • 如果参数是基本类型的话,传递的就是基本类型的字面量值的拷贝
  • 如果参数是引用类型,传递的就是实参所引用的对象在堆中地址值的拷贝