版权声明:转载请写明出处,谢谢! https://blog.csdn.net/wilson1068/article/details/87737182
简略介绍 Java 引用类型
Java 中的类型分为两大类:值类型和引用类型。
值类型就是基本数据类型(int, double, char, boolean 等)。
那么其它基本数据类型之外的类型都是引用类型(String,StringBuffer,Integer,Double等)。
存储空间分配
值类型在存储空间会在 stack (栈)中分配一块空间保存其数据。
引用类型在存储空间会在 heap (堆)中分配一块空间保存其数据,而在 stack (栈)中分配空间保存其在 heap 的地址信息(对外隐藏)。
那么以下数据的内存分配是:
// 值类型
void func(int x, float y);
int a = 10;
float b = 3.14;
func(a, b);
那么在值类型传递中,由于 func 函数处理是拷贝通过一份数据进行操作。显然无论 func 函数怎么处理,也不会因为原有数据 a,b 的值。
// 引用类型
void func(ClassOne x, ClassTwo y);
ClassOne a = new ClassOne("world");
ClassTwo b = new ClassTwo(900.9);
func(a, b);
而在引用类型传递中,由于 func 函数处理拷贝的一份数据是保存其 heap 数据的“地址信息”(对外隐藏)。那么 func 函数的一些操作,是有可能改变原有数据 a,b 实际表现的值。
其它情况
由此,是不是我们每一个函数操作类(class)实体的时候,都会改变外部实体的数据呢?
我们来看看下面的例子:
测试代码:
public static void test_int(int v) {
v += 10;
}
public static void test_Integer(Integer v) {
v += 10;
}
public static void test_String(String s) {
s += " <<<";
}
public static void test_StringBuffer(StringBuffer s) {
s.append(" <<<");
}
public static void main(String[] args) {
int a1 = 10;
System.out.println("a1 = " + a1);
test_int(a1);
System.out.println("a1 = " + a1);
Integer a2 = 10;
System.out.println("a2 = " + a2);
test_Integer(a2);
System.out.println("a2 = " + a2);
String s1 = new String("###");
System.out.println("s1 = " + s1);
test_String(s1);
System.out.println("s1 = " + s1);
StringBuffer s2 = new StringBuffer("###");
System.out.println("s2 = " + s2);
test_StringBuffer(s2);
System.out.println("s2 = " + s2);
}
测试结果:
a1 = 10
a2 = 10
a2 = 10
s1 = ###
s1 = ###
s2 = ###
s2 = ### <<<
为什么类 Integer 和 String 没有被修改呢?不是引用类型吗?
引用类型可以通过 stack(栈)的“地址信息”数据,访问到 heap(堆)的实体数据。
但是,谁说存储在 heap (堆)的数据一定可以修改呢?
Integer 和 String 都是 final 的引用类型,意味着其 heap (堆)的实体数据不可修改。