首先看图,当一个Java类被编译成Class之后,假如这个类称为A,并且A中引用了B,那么在编译阶段A是不知道B有没有被编译的,而且此时B也一定没有被加载,所以A 肯定不知道B的实际地址,那么此时在A的class文件中,将使用一个字符串S来代表B的地址,S就被称为符号引用,在运行时,如果A发生了类加载到了解析阶段会发现B还未被加载,那么将会触发B的类加载,将B加载到虚拟机中,此时A中B的符号引用将会被替换为B的实际地址,这被称为直接引用。这样也能真正的调用B了。
但是事情没有这么简单,了解多态的同学应该知道Java通过后期绑定的方式来实现多态,那么后期绑定这个概念又是如何实现的呢,其实就是这里的动态解析。接着上面所说,如果A调用的B是一个具体的实现类那么就称为静态解析,因为解析的目标类型很明确,而假如上层Java代码使用了多态,这里B]是一个抽象类或者是接口,那么B可能有两个具体的实现类C和D,此时B的具体实现并不明确,当然也就不知道使用那个具体类的直接引用来进行替换,既然不知道那就等一等吧,直到在运行过程中发生了调用,此时虚拟机调用栈中将会得到具体的类信息,这时候再进行解析,就能用明确的直接引用,来替换符号引用,这也就解释了为什么解析阶段有时候会发生在初始化阶段之后,这就是动态解析,用它来实现后期绑定。