值传递和引用传递
注:java中是值传递。
那么在进行赋值修改的过程中,引用类型的内部值也发生了改变? 这又是怎么回事?
参考链接: https://blog.csdn.net/pcwl1206/article/details/86550268
- 当传递方法参数类型为基本数据类型(数字以及布尔值)时,一个方法是不可能修改一个基本数据类型的参数。
- 当传递方法参数类型为引用数据类型时,一个方法将修改一个引用数据类型的参数所指向对象的值。
- 即使 Java 函数在传递引用数据类型时,也只是拷贝了引用的值罢了,之所以能修改引用数据是因为它们同时指向了一个对象,但这仍然是按值调用而不是引用调用。
Java是值传递。
- 当传的是基本类型时,传的是值的拷贝,对拷贝变量的修改不影响原变量;
- 当传的是引用类型时,传的是引用地址的拷贝,但是拷贝的地址和真实地址指向的都是同一个真实数据,因此可以修改原变量中的值;
- 当传的是String类型时,虽然拷贝的也是引用地址,指向的是同一个数据,但是String的值不能被修改,因此无法修改原变量中的值。
自己的代码例子:
- 基本数据类型:
package com.AL.base;
/**
* 值传递和引用传递。 java中是值传递. pass by value, pass by reference
* java内存中存储的东西内容: 堆:new的对象和数组, 栈:基本数据类型和引用类型
* 基本数据类型:值就直接保存在这个变量中; 引用类型:保存的地址值 是指向对象内容的地址,实际对象的地址【引用指向实际对象,实际对象中存放着内容】
*
* 如果参数是基本类型,传递的是基本类型的字面量值的拷贝。【当传的是基本类型时,传的是值的拷贝,对拷贝变量的修改不影响原变量】
* 如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。
*/
public class passByValue_BaseDataType {
public static void main(String[] args) {
int a = 10;
System.out.println("change方法调用前");
System.out.println("a:->" + a);
change(a);
System.out.println("change方法调用后");
System.out.println("a:->" + a);
}
public static void change(int a){
a = a + 10;
System.out.println("change方法中");
System.out.println("a :" + a);
}
}
结果:
change方法调用前
a:->10
change方法中
a :20
change方法调用后
a:->10
- 引用类型: 对于String 类型(final修饰,不可变)[其实 Integer类型也是]
package com.AL.base;
/**值传递和引用传递
* 对于 String 类型,引用类型。 在进行值改变的时候, 究竟是什么?
* 当传的是引用类型的时候,传递的是引用地址的拷贝,即拷贝地址和真实地址指向的是同一个对象,所以会改变原变量中的值。
*/
public class passByValue_String {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = "abcde";
System.out.println("change方法调用前");
System.out.println("str1 :" + str1);
System.out.println("str2 :" + str2);
change(str1);
change(str2);
System.out.println("change方法调用后");
System.out.println("str1 :" + str1);
System.out.println("str2 :" + str2);
}
public static void change(String str){
// str = str + "!!!!!!";
str = "alzn";
System.out.println("change方法中");
System.out.println("str :" + str);
}
/**
运行的结果为:
change方法调用前
str1 :abc
str2 :abcde
change方法中
str :alzn
change方法中
str :alzn
change方法调用后
str1 :abc
str2 :abcde
分析原因: 拿 str1 = "abc"举例
String是引用类型,栈中存放的变量是指向堆中 "abc" String类型的 地址值,这个地址指向堆中具体的值。
那么在调用change方法时,它会拷贝变量,拷贝的值是 引用地址,并不会拷贝堆中的数据。 所以,在传递引用类型时 会改变原变量中的值。
为什么这里 String没有改变呢???
栈中 0x10 指向 堆中"abc" String; 在调用时,会进行引用地址的拷贝 假设 0x11 中存放。 0x10和0x11两者均指向 abc,
在进行改变数据的时候,由于String的不可变性质, 则0x11会另外指向一个 alzn 在堆中的引用地址,不会改变原有的"abc"数据
*/
}
- 引用类型:StringBuffer,长度可变的字符串类型
package com.AL.base;
/**
* 值传递和引用传递:
* 关于StringBuffer的特性:StringBuffer是长度可变的,线程安全,在对元素进行操作的时候,会有 synchronized 修饰进行同步
* StringBuild 长度可变,但线程不安全
*/
public class passByValue_StringBuffer {
public static void main(String[] args) {
StringBuffer str1 = new StringBuffer("abc");
StringBuffer str2 = new StringBuffer();
str2.append("abcdef");
System.out.println("change方法调用前");
System.out.println("str1 :" + str1);
System.out.println("str2 :" + str2);
change(str1);
change(str2);
System.out.println("change方法调用后");
System.out.println("str1 :" + str1);
System.out.println("str2 :" + str2);
}
public static void change(StringBuffer str){
// str = str + "!!!!!!";
str.append("alzn");
System.out.println("change方法中");
System.out.println("str :" + str);
}
}
结果为:
change方法调用前
str1 :abc
str2 :abcdef
change方法中
str :abcalzn
change方法中
str :abcdefalzn
change方法调用后
str1 :abcalzn
str2 :abcdefalzn