static关键字详解
Java中static关键字用来修饰3类东西:变量,代码块,函数。
1.变量
static修饰的变量叫类变量/静态变量,对于类变量/静态变量在内存中只有一个拷贝(节省内存),JVM只分配一次内存,在加载类的过程中完成类变量/静态变量的内存分配,可用类名直接访问,也可以用new生成对象后访问。
2.代码块
static修饰的代码块叫静态代码块,是类中独立于类成员的代码块,在类中可以存在多个,位置任意,但不能存在于函数内部。JVM在加载类时执行该代码块,如果有多个静态代码块则按照它们在类中出现的顺序执行,且只执行一次,常用来完成初始化工作。
3.函数
static修饰的函数叫静态函数,被调用的时候不需要实例化对象,执行通过类名可以访问。它只能访问static修饰的函数和变量,不能访问其他需要实例化的成员,因此该类函数的内部不能出现this和super关键字。
java中类的加载步骤:
使用类是时,首先由ClassLoader将要使用的类加载进来。这个过程要经过三个步骤完成:装载、链接、初始化,其中链接有分为,校验、准备和解析三步。除解析外其他步骤严格按照顺序执行。这些步骤要完成的功能如下:
装载:查找和导入类或接口的二进制数据;
校验:检查导入的类或接口的二进制数据的正确性;
准备:给类的静态变量分配内存空间并初始化;
解析:将符号引入转化成直接引用,可选步骤;
初始化:激活类的静态变量的初始化代码和静态代码块。
关于静态代码块的初始化工作是各类面试中常考的知识点,下面通过一个简单的例子进行说明。
public class Parent {
static String name = "Parent";
{
System.out.println("Parent no static code block");
}
static {
System.out.println("Parent static block");
}
public Parent(){
System.out.println("Parent constructor");
}
}
public class Child extends Parent {
static String childName = "Child";
{
System.out.println("Child no static block");
}
static {
System.out.println("Child static block");
}
public Child(){
System.out.println("Child constructor");
}
}
public class Client {
public static void main(String[] args){
Child child = new Child();
}
}
如上代码经过编译运行后的输出结果如下:
Parent static block
Child static block
Parent no static code block
Parent constructor
Child no static block
Child constructor
通过上面的例子,我们可以了解到当new Child()时,执行顺序如下:1.父类的静态代码块,2.子类的静态代码块,3.父类的非静态代码块,4.父类的构造函数,5.子类的非静态代码块,6.子类的构造函数。
所以说new一个对象时,对象的初始化顺序是:如果父类有静态代码块,首先执行父类的静态代码块;如果子类有静态代码块,接着执行子类的静态代码块。如果父类有非静态代码块,再执行父类的非静态代码块,接着执行父类的构造函数。如果子类有非静态的代码块,再执行子类的非静态代码块,接着执行子类的构造函数。总结一句话就是:先执行父类的静态代码再执行子类的静态代码;接着执行父类的非静态代码和构造函数;接着执行子类的非静态代码和构造函数。
注意:调用子类的构造方法时,默认的是先查找父类不带参数的构造方法,若父类没有不带参数的构造方法,则必须在子类的构造方法中通过super关键字显示的调用,否则编译过程中会出错。