为什么静态变量、静态方法,不需要实例就可以访问?
其实这和类的加载有关系。
不放先看看类加载的过程:
1. 加载
首先说一点,这里说的加载,仅仅是类加载中的一个步骤。该阶段进行的工作是,将二进制字节码,加载到内存中。
具体可以分为如下三步:
- 通过一个类的全限定类名来获取定义此类的二进制字节流
- 将获取到的字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区中这个类的各种数据的访问入口
我们仔细的看看上面三个步骤。首先,是获取定义类的二进制字节流。从哪里获取?怎样获取?这些虚拟机规范都没有定义,所以可以有多种实现,例如我们可以通过jar包、class文件获取。
获取到二进制字节流之后,自然是要把二进制字节流代表的类信息,添加到方法区中。那么类信息具体是指什么呢?
这个类型的完整有效名
这个类型直接父类的完整有效名(除非这个类型是interface或是
java.lang.Object,两种情况下都没有父类)
这个类型的修饰符(public,abstract, final的某个子集)
这个类型直接接口的一个有序列表
除了以上的基本信息外,jvm还要为每个类型保存以下信息:
类型的常量池( constant pool)
域(Field)信息
方法(Method)信息
除了常量外的所有静态(static)变量
2. 连接
类加载的第二步为连接。连接又分为三个步骤:
- 验证
对二进制字节流进行验证。
- 格式验证
验证class文件格式是否符合java虚拟机规范 - 元数据验证
验证元数据是否符合java语义规范 - 字节码验证
验证方法体是否符合java语义规范 - 符号引用验证
校验发生在虚拟机将符号引用转化为直接引用的时候,是对类自身以外的信息进行匹配性校验。
- 格式验证
- 准备
为类变量、静态语句块分配内存,并进行初始化。 - 解析
符号引用转换为直接引用
解析动作主要是针对类或接口、字段、接口方法、类方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
3.初始化
到了初始化阶段,才真正开始执行类中定义的Java程序代码;在准备阶段中,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序指定的主观计划去初始化变量和其它资源。
参考《深入理解java虚拟机》