-
static关键字使用的场景
-
-
静态代码块
-
修饰类(只能修饰内部类)
-
静态导包(用来导入类中的静态资源,1.5之后的新特性)
-
static修饰成员变量和成员方法
- static修饰的成员属于类,随着类的加载而加载,不属于该类的实例化的某个对象,被类的所有成员共享(判断是否使用static关键字的条件),可通过类名调用;成员变量随着对象而存在,随着对象的消失而消失,成员变量只能通过对象名调用;
- static声明的成员变量属于静态成员变量,静态变量存放在 Java 内存区域的方法区;成员变量存储在堆内存;
- 在静态方法中没有this关键字,对于本类,静态方法只能访问本类的静态的成员变量和静态的成员方法;
补充:
静态区/方法区:
1.方法区里面有个静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量;
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量;
3.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域;
调用格式:
类名.静态变量名; 类名.静态方法名();
-
静态代码块
- 静态代码块定义在类中的方法外, 静态代码块在非静态代码块之前执行,即在类加载的时候就运行了,而且只执行一次(静态代码块—非静态代码块—构造方法);
- 一个类中的静态代码块可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果静态代码块有多个,JVM将按照它们在类中出现的先后顺序(即书写顺序)依次执行它们,每个代码块只会被执行一次;
- 静态代码块在类加载的时候就自动运行了,而不管是放在普通方法还是静态方法中,都是不能自动运行的;
静态代码块的格式:
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),该引用是指向创建它的外围类,但静态内部类没有;
- 静态内部类的创建是不需要依赖外围类的创建;
- 静态内部类不能使用任何外围类的非static成员变量和方法;
- 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; } }
-
静态导包
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); } }