在Java中存在值传递和引用传递,但是如何去区分两者呢,现在来说一下我自己的理解,希望能帮到需要的人理解这部分内容。
先来看一段概念:
值传递:传递的是值的拷贝,对传递的值做处理不会修改值本身(相应的理解可以思考虚拟机,我们传递的值是从虚拟机中拷贝的一份,原始的值是不会变。)
引用传递:将原数据作为参数进行传递,修改传递的值会修改原数据本身。 一句话总结:值传递不修改原数据,引用传递是直接操作原数据。
好了,看概念都知道说的什么,但是理解又是一回事,现在用代码来理解值传递和引用传递。
先上第一个例子:
public class Test {
public static void test(Integer i){
i = 7;
}
public static void main(String[] args){
int x = 0 ;
test(x);
System.out.println("x="+x); //输出i=0
}
}
即使我不写输出结果你们也能知道这个一定是输出i=0,我们看调用方法,传递给调用方法的参数是x=0,于是就相当于我们只是给调用方法的参数传递了一个数字0,因此在test方法中对传入的0做处理是不会影响原数据本身。
第二个例子:
public class Test {
public static void test(String str){
str = "world";
}
public static void main(String[] args){
String string = "hello";
test(string);
System.out.println(string); //输出hello
}
}
当我们参数类型改为字符串时,对于传入的字符串,在调用方法中并不存在修改自身的方式,其中 str=“world” 并没有修改存储在常量池中的的原数据,因此依然输出 hello。
第三个例子:
public class Test {
public static void test(StringBuffer str){
str.append("world");
}
public static void main(String[] args){
StringBuffer stringBuffer = new StringBuffer("hello ");
test(stringBuffer);
System.out.println(stringBuffer); //输出hello world
}
}
这个例子中在调用方法中多了一个append方法,该方法会对传入的参数做修改,同时改变常量池中的数据,append本身是对自身进行的操作,因此常量池中的hello会改变为hello world。
第四个例子:
public class Test {
public static void test(StringBuffer str){
str = new StringBuffer("hi");
str.append("world");
}
public static void main(String[] args){
StringBuffer stringBuffer = new StringBuffer("hello ");
test(stringBuffer);
System.out.println(stringBuffer); //输出hello
}
}
在这个例子中我们看到调用方法中对传入的参数进行了new对象,同时我们也知道new是新生成一个对象,并不会影响原来的对象,因此我们可以看到在test方法中我们new了一个新对象,新对象指向了hi这个字符串,同时对hi执行了append,这些操作都是对new对象做的操作,传入的hello对象并没有受到影响。因此还是输出hello。(该部分的理解可以结合虚拟机的存储结构进行理解。结构图就不画了。)
第五个例子:
public class Test {
public static void test(StringBuffer str){
StringBuffer str2 = new StringBuffer("Hi ");
str = str2;
str2.append("world");
System.out.println("str="+str); //输出Hi world
System.out.println("str2="+str2); //输出Hi world
}
public static void main(String[] args){
StringBuffer stringBuffer = new StringBuffer("hello ");
test(stringBuffer);
System.out.println(stringBuffer); //输出hello
}
}