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呢?
什么是求值策略?
求值策略是指编程语言中表达式的求值规则,通常分为两大类:
- 严格求值:总是在应用之前求值
- 非严格求值
什么是值传递?
值传递是指将原值拷贝一份后,将拷贝值传递
为什么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);