Java方法传参时是值传递还是引用传递?

  • 什么是求值策略?
  • 什么是值传递?
  • 为什么Java只支持值传递?
  • 深浅拷贝与赋值有什么区别?
  • 强、软、弱、虚引用有什么区别?



Java方法传参时是值传递还是引用传递?要回答这个问题,咱们先思考为什么会问这个问题,提问人真正的困惑是什么,想得到什么回答。按正常的理解,传参就是调用方把参数传递给被调用方,不就直接传递嘛,怎么还分值传递和引用传递呢?就像打篮球传球一样,直接把球扔过去就行了,还需要分怎么扔吗?另外什么是值传递?什么又是引用传递?

首先需要明确的是值传递和引用传递这两个基本概念,值传递和引用传递都来自计算机科学中对于运算的求值策略,值传递是指把真实值的拷贝传递出去,引用传递是指把真实值的引用传递出去,这两种求值策略体现在Java方法传参的区别是值传递之后的运算不会影响原来的真实值,因为传递的是真实值的拷贝;而引用传递之后的运算会影响真实值,因为传递的是真实值的引用,这里似乎有点类似与深浅拷贝的概念。

对于Java方法传参的求值策略,采用的是值传递,证明如下:
猜猜下面的代码输出是1还是2

public class MyTest {
    public static void main(String[] args) {
        int value = 1;
        addOne(value);
        System.out.println(value);
    }

    public static void addOne(int value) {
        value = value + 1;
    }
}

运行可知最后输出的是1,因为Java方法传参采用的是值传递,而在JVM栈帧中,基本数据类型就是其真实值,

再看下面的代码,输出是1还是2?

public class MyTest {
    public static void main(String[] args) {
        MyNumber myNumber = new MyNumber(1);
        addOne(myNumber);
        System.out.println(myNumber.getValue());
    }
    
    public static void addOne(MyNumber myNumber) {
        myNumber.setValue(myNumber.getValue() + 1);
    }
}

class MyNumber {
    private int value;

    public MyNumber(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

嗯,这次输出就是2,为什么呢?

再猜猜下面的代码输出是1还是2

public class MyTest {
    public static void main(String[] args) {
        MyNumber myNumber = new MyNumber(1);
        addOne(myNumber);
        System.out.println(myNumber.getValue());
    }
    
    public static void addOne(MyNumber myNumber) {
    	myNumber = new MyNumber(1);
        myNumber.setValue(myNumber.getValue() + 1);
    }
}

class MyNumber {
    private int value;

    public MyNumber(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

输出是1,为什么不是2呢?

什么是求值策略?

求值策略是指编程语言中表达式的求值规则,通常分为两大类:

  1. 严格求值:总是在应用之前求值
  2. 非严格求值

什么是值传递?

值传递是指将原值拷贝一份后,将拷贝值传递

为什么Java只支持值传递?

深浅拷贝与赋值有什么区别?

赋值:基本类型直接复制,引用类型复制引用地址
浅拷贝:创建一个新对象,新对象中的基本类型直接复制,引用类型复制引用类型
深拷贝:创建一个新对象,新对象中的基本类型直接复制,引用类型创建新对象

强、软、弱、虚引用有什么区别?

强引用【StrongReference】:从来不会被垃圾回收器回收,只有当JVM停止时才会终止,用于对象的一般状态

Object obj=new Object();

软引用[【SoftReference】:当内存不足时才会被垃圾回收器回收,用于对象缓存

Object obj=new Object();
SoftReference<Object> softReference = new SoftReference<>(obj);

弱引用【WeakReference】:只要垃圾回收器扫描到就会被回收(正常回收),用于对象缓存

Object obj=new Object();
WeakReference<Object> weakReference = new WeakReference<>(obj);

虚引用【PhantomReference】:只要垃圾回收器扫描到就会被回收(正常回收),用于跟踪对象的垃圾回收

Object obj=new Object();
// 创建虚引用,要求必须与一个引用队列关联
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(obj, queue);