static 概念
Java中static关键字的作用
(1)为特定的数据类型或对象分配单一的存储空间.
(2)实现某个方法或属性与关联在一起.
static关键字作用
1、变量
static修饰的变量我们称之为静态变量,没有用static修饰的变量称之为实例变量,他们两者的区别是:
1、静态变量是随着类加载时被完成初始化的,它在内存中仅有一个,且JVM也只会为它分配一次内存。
2、同时类所有的实例都共享静态变量,可以直接通过类名来访问它。
3、实例变量则不同,它是伴随着实例的,每创建一个实例就会产生一个实例变量,它与该实例同生共死。
所以我们一般在这两种情况下使用静态变量:对象之间共享数据、访问方便。
2、方法
static修饰的方法我们称之为静态方法,我们通过类名对其进行直接调用。由于它在类加载的时候就存在,它不依赖于任何实例,所以static方法必须实现,也就是说它不能是抽象方法abstract
static方法时类中的一种特殊方法,我们只有在真正需要他们的时候才会将方法声明为static。如Math类的所有方法都是静态static的。
3、代码块
被static修饰的代码块,我们称之为静态代码块,静态代码块会随着类的加载一块执行,而且他可以随意放,可以存在于该了的任何地方。
4、类
I.内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。
II.非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。
III.非静态内部类不能脱离外部类实体被创建,非静态内部类可以访问外部类的数据和方法。
public class OuterClass {
private static String msg = "GeeksForGeeks";
// 静态内部类
public static class NestedStaticClass{
// 静态内部类只能访问外部类的静态成员
public void printMessage() {
// 试着将msg改成非静态的,这将导致编译错误
System.out.println("Message from nested static class: " + msg);
}
}
// 非静态内部类
public class InnerClass{
// 不管是静态方法还是非静态方法都可以在非静态内部类中访问
public void display(){
System.out.println("Message from non-static nested class: "+ msg);
}
}
}
class Main
{
// 怎么创建静态内部类和非静态内部类的实例
public static void main(String args[]){
// 创建静态内部类的实例
OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();
// 创建静态内部类的非静态方法
printer.printMessage();
// 为了创建非静态内部类,我们需要外部类的实例
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
// 调用非静态内部类的非静态方法
inner.display();
// 我们也可以结合以上步骤,一步创建的内部类实例
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
// 同样我们现在可以调用内部类方法
innerObject.display();
}
}
static的局限
1、它只能调用static变量
2、它自能调用static方法
3、不能以任何形式引用this、super
4、static变量在定义时必须要进行初始化,且初始化时间要早于非静态变量
利用static 的机制实现的单例模式
public class Singleton {
private Singleton() {}
private static class SingletonHolder{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
熟悉 Java 类加载机制的都知道,当第一次访问类中的静态字段时,会触发类加载,并且同一个类只加载一次。静态内部类也是如此,类加载过程由类加载器负责加锁,从而保证线程安全。此种单例模式更加简洁明了,不容易出错。