参考自:[https://blog.csdn.net/ns_code/article/details/17881581]
重点
- 程序均在内存中执行,变量(方法)只有存放于内存中时,才能被访问
- 类的静态成员(变量或方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问。
- 非静态成员(变量和方法)属于类的对象,只有在类的对象产生时(创建实例-new)才会分配内存,然后通过实例去访问。
类加载过程
类从被加载到虚拟机中开始,到卸载出内存为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。如图所示:
其中类加载的过程中包括了加载、验证、准备、解析、初始化五个阶段。
这五个阶段除了解析其他四个阶段发生的顺序是确定的,解析阶段在某些情况下考研在初始化阶段之后,是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。
Note:这几个阶段是顺序开始,并不是顺序进行或顺序完成。通常是互相交叉混合进行,在一个阶段的执行过程中调用或激活另一个阶段。
Java中绑定:把一个方法的调用与方法所在的类关联起来,分为静态和动态绑定。
- 静态绑定:前期绑定。在程序执行前已经绑定。java中只有final、static、private和构造方法是前期绑定的。
- 动态绑定:即晚期绑定或运行绑定。在java中,几乎所有的方法都是后期绑定的。
准备阶段
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意:
- 这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在Java堆中。
- 这里所设置的初始值通常情况下是数据类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。
假设一个类别量定义为:
public static int value = 3
那么变量value在准备阶段过后的初始值为0,而不是3,因为这个时候未执行任何java方法,而把value赋值为3的putstatic指令是在程序编译后,存放于类构造器<clinit>()方法之中的,所以把value赋值为3的动作将在初始化阶段才会执行。
Java中所有基本数据类型以及reference类型的默认零值:
数据类型 | 默认零值 |
---|---|
int | 0 |
long | 0L |
Note:
- 对基本数据类型来说,对于类变量(static)和全局变量,如果不显式地对其赋值而直接使用,则系统会为其赋予默认的零值,而对于局部变量来说,在使用前必须显式地为其赋值,否则编译时不通过。
- 对于同时被static和final修饰的常量,必须在声明的时候就为其显式地赋值,否则编译时不通过;而只被final修饰的常量则既可以在声明时显式地为其赋值,也可以在类初始化时显式地为其赋值,总之,在使用前必须为其显式地赋值,系统不会为其赋予默认零值。
- 对于引用数据类型reference来说,如数组引用、对象引用等,如果没有对其进行显式地赋值而直接使用,系统都会为其赋予默认的零值,即null。
- 如果在数组初始化时没有对数组中的各元素赋值,那么其中的元素将根据对应的数据类型而被赋予默认的零值。
网友评论