前言: 了解对象,数据在内存的细节, 有助于程序员设计出更加合理地结构。
指针和对象的关系:指针指向对象在内存中首地址的位置
指针之间赋值:
1 指针间的赋值与基本类型赋值一样,它并不会引起对对象的操作。
2 指针之间赋值是将 指针的内容赋值到另一个指针中,后者的内容将会丢失。
对象的内存表示:
字符串的内存表示:
串的内存表示
串是最常用的类,也是Java特殊对待的类型之一(另一个是数组)。
串是定常的。无论一个串存储在哪里,它所包含内容是不可改变的。
字面常量表达的串(eg: "abc"),存储在特殊的位置:串池中。串池的特点是:不允许重复,也不会去回收垃圾。
串池: (注意 里面仅存放 字面常量, 并且不会被垃圾回收)
看下面案例:
public static void main(String[] args) {
String a = "abc";
String b = "ab" + "c";
//System.out.println(a == b); true b做计算后又会引用串池中的 abc, 因此 两者表达的内存地址是一致的
String c = new String("abc");
System.out.println(a == c); // false c的操作会在堆内存中重新创建一个空间放abc, 此时不再应用到串池中的内容,因此两者的内的物理地址不一样 结果为false
}
数组的内存表示:
数组是Java特殊对待的类型。一个数组中的所有元素占据一片连续的内存空间。
数组的长度在创建时固定,将来无法修改。
数组在随机访问的时候速度最快,但在插入、删除元素时却十分吃力。
数组的每个元素在内存中占用的空间大小一样。
数组不能再原有大小下继续开辟空间,
因为鉴于数据元素占用内存地址连续这个前提下,在数组最后数据位置的下一个地址
无法预料这个地址是否被别的对象占用,因此数组不支持动态添加长度,只能重新创建更长一个新数组并赋值。
同时,在数组中间位置删除元素也给数组带来很繁琐的操作,后续元素必须依次回挪到上一个 内存地址上才能保证数组元素
地址保持联系性这个特性。
关于多态是如何找到真实对象的:
对于每一个对象,内存中总是有一个字段,此字段指向了该对象的类型信息对象,真实类型是=右侧的类型
同时,每个对象都有自己的父类型信息指针,指向其父亲,
对于如下代码, a的对象类型信息是C,执行a.f()时,a的祖先们通过自身的父类型信息指针将祖先各自连接成一个链条,并自动匹配具体调用哪个类的方法
A a = new C();
a.f();