【Java基础】static关键字还没掌握吗,看这篇就够了

static关键字详解

结论

先上结论,一会我们用实例讲解。

  • static关键字表示静态的,可以修饰变量、方法、类,还可以实现静态代码块。
  • 静态变量统一存储在元空间中(在JDK1.8之后,1.7是方法区),具体可以看JVM内存详解。
  • 如果一个字段是静态的基本类型,你没有初始化它,那么它就会获得基本类型的标准初值。如果它是对象引用,那么它的默认初值就是 null。(摘自《On Java8》)

static修饰变量及方法

首先由static修饰的变量是静态成员变量,它是属于类的,所以可以直接使用类名去访问。

static变量在内存中独占一份,在类初次加载时才会进行初始化。

而static方法同理,由下图所示:

【Java基础】static关键字还没掌握吗,看这篇就够了_第1张图片
在图片中我们可以看到,类名可以直接对静态成员变量和方法访问,但是对非静态进行引用会有爆红提示,这是因为在静态方法内部,不允许引用非静态成员与方法。具体原因下一节进行讲解。

static与JVM的关系

下面先给出Java虚拟机经典的内存模型。
【Java基础】static关键字还没掌握吗,看这篇就够了_第2张图片
static变量与方法都存储在MetaSPACE(在JDK1.7前是叫做方法区)中,而普通变量存储在堆区中,那么JVM对类进行加载是一个怎样的步骤呢?

我们引用《深入理解JVM》这本书的讲解,可以知道类的加载过程。
【Java基础】static关键字还没掌握吗,看这篇就够了_第3张图片

而我们由static修饰的所有东西都在准备阶段进行初始化,而非静态的是在类实例化为对象阶段才会进行初始化,注意不要混淆实例化和加载

所以我们可以解释上一节的问题,静态函数中不可以访问非静态成员。

static静态代码块和初始化顺序

static除了修饰变量、函数,还可以使用静态代码块,可以使我们有些代码启动即执行,下面有这样一个例子。

public class Father {

    static {
        System.out.println("父类静态代码块");
    }

    {
        System.out.println("父类代码块");
    }

    public Father() {
        System.out.println("父类构造函数");
    }
}

class Son extends Father{

    static {
        System.out.println("子类静态代码块");
    }

    {
        System.out.println("子类代码块");
    }

    public Son() {
        System.out.println("子类代码块");
    }

    public static void main(String[] args) {
        Son son = new Son();
    }
}

答案如下:

父类静态代码块
子类静态代码块
父类代码块
父类构造函数
子类代码块
子类代码块

总结来说,静态代码总是优先执行,之后就是父类优先于子类。

你可能感兴趣的:(Java基础,java,jvm)