一、基本类型 和 引用类型的不同之处
int num = 10;
String str = "hello";
首先变量其实是堆栈中的地址索引。然后 基本类型的数据直接保存在堆栈中,而对象是保存在堆中,堆栈中保存的是该对象在堆中的地址,这个地址就是所谓的引用
二、赋值运算符(=)的作用
num = 20;
str = "java";
对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。
如上图所示,”hello” 字符串对象没有被改变。(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)
三、调用方法时发生了什么?参数传递基本上就是赋值操作。
num = 20;
str = "java";
func(num,str);
public void func(int n,String s){
n=30;
s+="haha";
// do something with s
}
n变为30,num不受影响;s虽然是对象类型,但是由于String是不可变类型,因此并不会影响到原来的str变量。所以结果如下:
如果str是StringBuilder对象的话,就会改变,结果如下:
总结
在java中,不管原始参数的类型是什么,参数都是按值传递的。
每当一个方法被执行时,在堆栈中就会为每个参数创建一个拷贝,这个拷贝被传递到方法的内部,这个拷贝分以下2种情况:
- 如果参数是基本类型,那么在堆栈中复制的就是这个参数的值
- 如果是对象,那么在堆栈中传递的便是指向真正对象数据的新的引用。这个新的引用被传递到方法内部。
因此关于参数在方法中被修改后,会不会影响到原始变量,根据上面的原理:
- 修改一个基础类型的参数,不会影响原始数据;
- 修改一个对象参数(数组、集合、map、类)的引用时,永远不会影响到原始的引用;
- 修改一个对象参数的属性时,会影响原始对象
public static void main(String[] args) {
DuplicatenNum app = new DuplicatenNum();
int a1=5;
app.fun1(a1);
System.out.println(a1);
TreeNode a2=new TreeNode(5);
app.fun2(a2);
System.out.println(a2);
int[] a2_2={1,2};
app.fun2_2(a2_2);
System.out.println(a2_2[0]);
List<Integer> list=new ArrayList<>();
list.add(1);
app.fun3(list);
System.out.println(list);
}
public void fun1(int a) {
a=10;
}
public void fun2(TreeNode root) {
root=new TreeNode(10);
}
public void fun2_2(int [] arr) {
arr = new int[4];
}
public void fun3(List<Integer> list){
list.add(2);
}
输出:
5
TreeNode{val=5, left=null, right=null}
1
[1, 2]