Java中static关键字

  • static关键字使用的场景

  1. 修饰成员变量和成员方法

  2. 静态代码块

  3. 修饰类(只能修饰内部类)

  4. 静态导包(用来导入类中的静态资源,1.5之后的新特性)

  • static修饰成员变量和成员方法

  1. static修饰的成员属于类,随着类的加载而加载,不属于该类的实例化的某个对象,被类的所有成员共享(判断是否使用static关键字的条件),可通过类名调用;成员变量随着对象而存在,随着对象的消失而消失,成员变量只能通过对象名调用;
  2. static声明的成员变量属于静态成员变量,静态变量存放在 Java 内存区域的方法区;成员变量存储在堆内存;
  3. 在静态方法中没有this关键字,对于本类,静态方法只能访问本类的静态的成员变量和静态的成员方法;

  补充:

    静态区/方法区:
    1.方法区里面有个静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量;

    2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量;

    3.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域;

  调用格式:

类名.静态变量名;
类名.静态方法名();

  

  • 静态代码块

  1. 静态代码块定义在类中的方法外, 静态代码块在非静态代码块之前执行,即在类加载的时候就运行了,而且只执行一次(静态代码块—非静态代码块—构造方法);
  2. 一个类中的静态代码块可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果静态代码块有多个,JVM将按照它们在类中出现的先后顺序(即书写顺序)依次执行它们,每个代码块只会被执行一次;
  3. 静态代码块在类加载的时候就自动运行了,而不管是放在普通方法还是静态方法中,都是不能自动运行的;

  静态代码块的格式:

static {    
  方法体;  
}

  

  示例1:

public class StaticDemo {

    static {
        i = 1;
        System.out.println(i);
    }

    private static int i;
}

  程序运行会报错,不能在字段定义前访问(System.out.println(i); 这里报错);静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问;

  示例2:

public class StaticDemo {
    private static int i;

    static {
        i = 1;
        System.out.println(i);
    }

}

  与示例1不同的是静态变量的定义放在了静态代码块之前,程序运行正常;

  • 静态内部类

  静态内部类与非静态内部类之间存在一个最大的区别,非静态内部类在编译完成之后会隐含地保存着一个引用(this),该引用是指向创建它的外围类,但静态内部类没有;

  1. 静态内部类的创建是不需要依赖外围类的创建;
  2. 静态内部类不能使用任何外围类的非static成员变量和方法;
  3. static修饰类只能修饰内部类;

  示例:

public class Singleton {
    
    //声明为 private 避免调用默认构造方法创建对象
    private Singleton() {
    }
    
    //声明为 private 表明静态内部该类只能在该 Singleton 类中被访问
    private static class SingletonHandler {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHandler.INSTANCE;
    }
}

  当 Singleton类加载时,静态内部类 SingletonHandler 没有被加载进内存;只有当调用 getInstance()方法从而触发 SingletonHandler.INSTANCE 时 SingletonHandler才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次;这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持;

  外部类加载时并不需要立即加载静态内部类,静态内部类不被加载则不会进行初始化,故而不占内存;

  • 静态导包

  import static连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法;

  格式为:

import static packageName.className.*
import static packageName.className.methodName

  示例:

import static java.lang.Math.max;
 
public class StaticDemo {
	public static void main(String[] args) {
 
		int max = max(0, 1);
		System.out.println(max);
	}
}

  

原文地址:https://www.cnblogs.com/coder-zyc/p/10374349.html