static关键字
1.静态变量
1、个数:在内存中只有一份,被类的多个对象所共享、
2、加载时机:随着类的加载而加载,由于类只会加载一次,故静态变量也只有一份
3、内存位置:jdk6及之前存放在方法区;jdk7及之后存放在堆区
4、调用者:类 / 对象
5、消亡时机:随着类的卸载而消亡
6、开发中,什么时候需要将属性声明为静态的?
- 判断当前类的多个实例是否能共享此成员变量,且其值是相同的
- 开发中,常将一些常量声明是静态的。如:Math.PI
2.静态方法
1、包含:类方法、静态方法
2、通过”类.静态方法“直接调用静态方法
3、静态方法内可以调用静态的属性或静态的方法(类加载时已被加载),不可以调用非静态的结构(还没有被加载,在类实例化后才被加载,之后才能调用)
4、static修饰的方法内不能使用this/super,[属性和方法的前缀默认使用当前类来调用,可略]
5、补充:在类的非静态方法中,可以调用当前类中的静态结构(属性、方法)(已被加载,故可调用)或非静态结构(属性、方法)
6、开发中,什么时候需要将方法声明为静态的?
- 方法内操作的变量如果都是静态变量,则此方法建议声明为静态方法
- 开发中,常将工具类中的方法声明为静态方法。如:Array类、Math类
3.单例模式(Singleton)
介绍:采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
实现方式:
- 饿汉式(比较饿,上来就要实例对象)
”立即加载“,随着类的加载,当前唯一的实例也被加载
优点:写法简单,由于内存中较早加载,使用更方便,更快。
是线程安全的。
缺点:内存中占用时间比较长(随着类的加载而加载)。体现为内存泄漏(本身是垃圾,但是GC还没有被回收)。
class Bank{ //1.类的构造器私有化 private Bank(){ } //2.在类的内部创建当前类的实例,并私有化private // [ 立即加载 static 随着类的加载而加载静态的对象 较早的出现在内存存在,需要的时候调用即可] // [ 生命周期较长 ] // 内存泄露:本身是垃圾,但是GC还没有被回收 private static Bank instance = new Bank(); //3.使用getXxx()方法获取当前类的实例,必须声明为static的 public static Bank getInstance(){ return instance; } }
- 懒汉式(比较懒,用的时候再加载)、
”延迟加载“,需要使用对象的时候再创建
优点:再需要的时候再创建,节省内存空间
缺点:线程不安全
class GirlFriend{ //1.类的构造器私有化 private GirlFriend(){} //2.声明当前类的实例,[null,没有创建对象] private static GirlFriend instance = null; //3.通过getXxx()获取当前类的实例,如果未创建,则在方法内部进行创建 // [需要对象时才创建(延迟加载),空间上有一些节省] // [线程不安全,当第一个对象调用没完成时,第二个也加载进来(两个对象),造成冲突] private static GirlFriend getInstance(){ if (instance == null){ instance = new GirlFriend(); } return instance; } }
4.代码块
代码块没有名,故只能自动执行
- 静态代码块
1、格式:static{…}
2、加载时机:随着类的加载而加载(静态的、与类的生命周期相关,由于类的加载只会执行一次,进而静态代码块的加载也只会执行一次
3、作用:用来初始化==类==的信息
4、内部可以声明变量、调用属性或方法、编写输出语句等操作
5、静态代码块(类先加载)的执行先于非静态代码块(对象后加载)
6、静态代码块内部只能调用静态的结构[原因:非静态的还没有被加载,调用不到](即静态的属性、方法),不能调用非静态的结构(即非静态的属性、方法)
7、开发中:对静态的属性做的一些赋值,相当于需要一个自动会调用的,且仅调用一次的几行代码,最合适的位置就是静态代码块
- 非静态代码块(普通代码块)
1、格式:{…}
2、加载时机:随着对象的创建而执行,非静态的,只和对象的创建有关,每创建当前类的一个实例,就会执行一次非静态代码块
3、作用:用来初始化对象的信息
4、内部可以声明变量、调用属性或方法、编写输出语句等操作
5、如果声明有多个非静态代码块,则按照声明的先后顺序执行
6、非静态代码块内部可以调用静态的结构[原因:静态结构再加载类时已经加载完成,可以调用](即静态的属性、方法),也可以调用非静态的结构(即非静态的属性、方法)
7、对非静态的属性做的一些赋值
5.为什么说静态结构随着类的加载而加载
-
静态结构成员在Java中被声明为static,它们属于类本身的,而不是类的任何一个对象。
-
这些成员随着类的加载而加载,是因为它们需要在一个类的对象被创建之前就存在并可供访问
-
在Java中,一个类首次被使用时(无论是创建对象、调用静态方法还是访问静态字段),如果该类尚未被加载到JVM中,则会触发类的加载过程。类的加载包括加载、验证、准备、解析和初始化五个阶段。在这些阶段中,静态变量和静态代码块会在“初始化”阶段被执行。这意味着静态成员是随着其所属类的加载而加载的。