简略介绍 Java 引用类型

版权声明:转载请写明出处,谢谢! https://blog.csdn.net/wilson1068/article/details/87737182

简略介绍 Java 引用类型

Java 中的类型分为两大类:值类型和引用类型。

值类型就是基本数据类型(int, double, char, boolean 等)。

那么其它基本数据类型之外的类型都是引用类型(StringStringBufferIntegerDouble等)。

存储空间分配

值类型在存储空间会在 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 (堆)的实体数据不可修改。

final 引用类型(String)-内存存储

final 引用类型(StringBuffer)-内存存储

猜你喜欢

转载自blog.csdn.net/wilson1068/article/details/87737182