刚开始学习static关键字的时候,对于static关键字的认识还只是停留在可以和final关键字连用来定义静态常量,static+final在定义时就必须赋值,存放在方法区的静态常量池中,今天整理一下static关键字的用法和意义。
static存在的主要意义
static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法。
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。例如:视频中为每个公司
1.静态代码块
含义:在类中使用static修饰的成员代码块, 我们称其为静态代码块, 在类加载时执行。 每次程序启动到关闭 ,只会 执行一次的代码块。
- 关于static静态代码块的五个知识点
1、Java静态代码块中的代码会在类加载JVM时运行,且只被执行一次
2、静态块常用来执行类属性的初始化
3、静态块优先于各种代码块以及构造函数,如果一个类中有多个静态代码块,会按照书写顺序依次执行
4、静态代码块可以定义在类的任何地方中除了方法体中【这里的方法体是任何方法体】
5、静态代码块不能访问普通变量
这里先贴一段代码
public class Test {
static{
System.out.println("test static 1");
}
static{
System.out.println("test static 2");
}
public static void main(String[] args) {
}
}
看完代码发现main方法中什么代码都没有,但是运行结果如下:
运行结果: test static 1 test static 2
这是因为static修饰的代码块在类加载的时候就已经加载,即使main方法中没有语句,但是静态代码块中的语句却可以随着类加载运行。
针对知识点4静态代码块不能存在任何方法体的原因,是由于普通方法通过类加载后new出实例对象,再通过对象调用了这个方法,而静态代码块在加载类的时候就已经运行。静态方法在类加载的时候也加载了,但为什么不能存在于静态方法中呢,我看了大佬的解释是:静态方法虽然已经加载,但是必须要通过类名或者对象名才能够访问,相对于静态代码块,静态代码块是主动运行的,不管是哪种方法,我们需要明确静态代码块存在在类加载的时候就自动运行,所以不管放在静态方法还是普通方法中,静态代码块都无法主动运行。
而静态代码块无法访问普通变量更好理解,普通变量有实例对象调用,静态代码块加载的时候并未new实例对象,也就无法调用普通变量了。
2.静态变量
含义: 被static修饰的变量是独立于该类的任何对象。
- 关于静态变量的几个知识点:
1.静态变量在内存中只有一个拷贝,jvm只为静态分配一次内存(可以理解为所有对象公用)
2.仅在类第一次被加载时被初始化,切必须赋值。
3.能通过类名和对象来访问(不建议使用对象)
对于1的理解是static变量在类加载的时候分配空间,创建对象的时候不会重新分配,它独立于任何对象。
对3的通过类名访问是因为static变量优先于对象存在,即使没有创建对象,但是加载了类后,就可以访问静态变量,静态变量>实例变量
使用场景
- 一般在对象之间共享值
- 方便访问变量
3.静态方法
含义: static修饰的方法,可以通过类名调用。
- 关于静态方法需要注意的地方
1.可以通过类名访问
2.不能使用this和super关键字,不能访问自己类中不带static的成员变量和成员方法
3.一个类内部方法一般是非静态的,在需要方便其他类调用时将其声明为静态
2中不能使用this关键字对原因是static方法独立于对象,this关键字绑定于非静态对象,static方法不能访问,但是其他非静态方法可以调用静态方法。对于不能使用super关键字的原因也很简单,super关键字是指向父类对象,是其父类对象的引用,但是静态方法在对象创建之前就存在,super指向的对象不存在,就会出错。
特比注意
静态方法可以被继承,但是不能被重写,而是被隐藏。因为静态方法调用时直接通过类名调用,不需要继承就能调用,多态之所以能够实现依赖于继承、接口和重写、重载(继承和重写最为关键)。有了继承和重写就可以实现父类的引用指向不同子类的对象。重写的功能是:"重写"后子类的优先级要高于父类的优先级,但是“隐藏”是没有这个优先级之分的。
静态属性、静态方法和非静态的属性都可以被继承和隐藏而不能被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象。非静态方法可以被继承和重写,因此可以实现多态
(摘自csdn zhouhong1026)