符号引用
符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可。
就是目标类里全局唯一的一个完整的名字,包括类名、包名。符号引用都是存储在 java的常量池中,方法调用就是通过常量池来指向方法的符号引用,将其作为参数。
例如, 在Java中, 一个Java类将会编译成一个class文件。在编译时,java类并不知道所引用的类的实际地址, 因此只能使用符号引用来代替。
直接引用
(1)直接指向目标的指针(指向对象,类变量和类方法的指针)(2)相对偏移量。(指向实例的变量,方法的指针)(3)一个间接定位到对象的句柄
就是拿到我想要的方法、变量的内存地址(这件事在编译期间 java 是做不到的)
符号引用转化为直接引用
有两种,静态解析和动态链接(动态链接信息存储于栈帧)
- 静态解析
符号引用在类加载阶段或者是第一次使用时就会转化为直接引用,即静态解析
- 动态链接
符号引用在每次运行期间转化为直接引用,即动态链接,体现了 java 的多态性
Animal a = new Cat(); // 1
a.sleep();
a = new Dog(); //2
a.sleep();
a = new Lion(); //3
a.sleep();
1、2、3创建的实例只有在程序处于运行期的时候,才可以动态的识别出来,程序编译期间,从字节码角度看,都是调用 Animal 实例,而非 Cat、Dog、Lion 实例 invokevirtual 动态派发的指令,看到是调用 Animal 的实例方法,但是会检查此刻 a 真正指向的对象是谁,从而对 Animal 的实例调用转化为对真正指向的那个实例的特定 sleep 方法的调用