这是我参与「第四届青训营 」笔记创作活动的第10天,由于在学习HDFS底层代码时多次遇到static关键字的运用,特地总结了一下运用办法。

Java static关键字剖析

static目的

java中的static关键字首要用于内存管理。

static规模

运用规模:java static关键字能够用在变量、办法、代码块和嵌套类中。

作用规模:static关键字归于类,而不是类的实例。

静态(static)润饰

  1. 变量、办法:称为类变量/办法、静态变量/办法;润饰变量或办法,表示这个变量/办法归于这个类,而不归于单个目标
  2. 代码块:称为静态代码块;润饰代码块,表示该代码块为静态代码块
  3. 嵌套类:称为静态内部类;润饰内部类,表示该类为静态内部类。可用于完结单例形式。
  4. 可用于润饰import,进行静态导包,导入类中所有静态办法。最常见的运用场景是在JUnit进行单元测试时。

静态变量

类的成员变量能够分为以下两种:

静态变量(或称为类变量),指被 static 润饰的成员变量。

实例变量,指没有被 static 润饰的成员变量。

静态变量与实例变量的差异如下:

1)静态变量

运行时,Java 虚拟机只为静态变量分配一次内存,加载类过程中完结静态变量的内存分配。

在类的内部,能够在任何办法内直接拜访静态变量。

在其他类中,能够经过类名拜访该类中的静态变量。

2)实例变量

每创立一个实例,Java 虚拟机就会为实例变量分配一次内存。

在类的内部,能够在非静态办法中直接拜访实例变量。

在本类的静态办法或其他类中则需求经过类的实例目标进行拜访。

静态变量在类中的作用如下:

静态变量能够被类的所有实例共享,因此静态变量能够作为实例之间的共享数据,添加实例之间的交互性。

如果类的所有实例都包括一个相同的常量属性,则能够把这个属性界说为静态常量类型,从而节约内存空间。例如,在类中界说一个静态常量 PI。

静态变量的优点:它能使程序存储器高效(即它节约内存)。

静态办法

同成员变量,成员办法也能够分为以下两种:

静态办法(或称为类办法),指被 static 润饰的成员办法。

实例办法,指没有被 static 润饰的成员办法。

静态办法与实例办法的差异:

静态办法,归于类,而不归于类的目标。

  • 它经过类直接被调用,无需创立类的目标。
  • 静态办法中,不能运用 this 关键字,也不能直接拜访所属类的实例变量和实例办法;
  • 静态办法中,能够直接拜访所属类的静态变量和静态办法。
  • 同this 关键字,super 关键字也与类的实例相关,静态办法中不能运用 super 关键字。

实例办法,可直接拜访所属类的静态变量、静态办法、实例变量和实例办法。

静态办法与静态变量优点:

  • 归于类级别,无需创立目标就即可直接运用,运用方便。
  • 全局仅有,内存中仅有,静态变量能够仅有标识某些状况。
  • 类加载时候初始化,常驻在内存,调用方便方便。

静态办法与静态变量缺点:

  • 静态办法不能调用非静态的办法和变量。
  • 不能运用this和super关键字。

静态办法与静态变量适用场景:

  1. 静态办法,最合适工具类中办法的界说;比方文件操作,日期处理办法等。
  2. 静态办法,合适进口办法界说;比方单例形式,因从外部拿不到结构函数,所以界说一个静态的办法获取目标十分有必要。
  3. 静态变量合适全局变量的界说;举例:用一个布尔型静态成员变量做控制标志。

静态代码块

界说:静态代码块,是 Java 类中的 static{ } 润饰的代码。

作用:用于类初始化时,为类的静态变量赋初始值,提升程序性能。

静态代码块的特色如下:

静态代码块,有点类似于一个办法,但不能够存在于任何办法体内。

静态代码块,能够置于类中的任何地方,类中能够有多个静态初始化块。

Java 虚拟机在加载类时履行,将只需求进行一次初始化的操作放在 static 代码块。

类中含多个静态代码块,Java虚拟机将按它们在类中出现的顺序依次履行,且都履行一次。

同静态代码块与静态,不能直接拜访类的实例变量和实例办法,需经过类的目标拜访。

静态类

java中一个类要被声明为static的,只要一种状况,就是静态内部类(内嵌类)。如在外部类声明为static的,程序会编译都不会经过。

1、静态内部类,跟静态办法一样,只能拜访静态成员变量和办法,不能拜访非静态办法和属性。

2、一般内部类,能够拜访任意外部类的成员变量和办法。

3、静态内部类,能够声明一般成员变量和办法,而一般内部类不能声明static成员变量和办法。

4、静态内部类,能够单独初始化。

可用于完结单例形式。

public class StaticSingleton {
    /**
     * 只要当显式调用getInstance()办法之后,这里的静态内部类SingletonHolder才会被加载
     * 从而将INSTANCE初始化
     * 因此,经过静态内部类完结的单例形式是懒汉式的
     */
    private static class SingletonHolder {  // 经过静态内部类持有实例
        private static final StaticSingleton INSTANCE = new StaticSingleton();
    }
    private StaticSingleton() { }   // 用private躲藏结构办法
    public static StaticSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

static变量存储在办法区(Method Area)

办法区是被所有线程共享,所有字段和办法字节码,以及一些特别办法,如结构函数,接口代码也在此界说,简单说,所有界说的办法的信息都保存在该区域,此区域归于共享区间。

静态变量(static)、常量(final)、类信息(结构办法、接口界说)(Class)、运行时的常量池存在办法区中,可是实例变量存在堆内存中,和办法区无关。