前几天去面试,突然被问到Java关键字中的static和final,有点懵逼,有些概念性的东西竟然忘了,痛定思痛,故打算这样一篇博客来复习一下。
一、static
静态修饰符,可作用在变量、方法,方法块,类(内部类),所对应的调用时机和调用次数有所不同,主要分为以下几种情况:
1、作用在变量和方法块
public class ClassE {
static int a = 1;
static{
System.out.println("ClassE静态代码块");
}
public ClassE() {
System.out.println("ClassE构造");
}
public static void main(String[] args) {
ClassE classE = new ClassE();
ClassE classE2 = new ClassE();
}
}
运行结果:
ClassE静态方法块
ClassE构造
ClassE构造
初始化一个类时,首先按代码顺序,初始化类中的静态变量和执行类中的静态代码块,然后在调用构造方法。但是应该注意的是,静态变量的初始化和静态代码块的执行,只会在第一次调用该类时执行仅有的一次!!
此外,如果调用类中的静态方法,也会先执行该类中所有静态变量的初始化和静态代码块后,再调用该静态方法,也是只会在第一次调用该类时执行仅有的一次(不管调用该类中任意一静态方法,都只会在第一次调用时执行且只会执行一次),例如:
public class ClassE {
static int a = 1;
static{
System.out.println("ClassE静态方法块");
}
public ClassE() {
System.out.println("ClassE构造");
}
static void fun1(){
System.out.println("调用静态方法1");
}
static void fun2(){
System.out.println("调用静态方法2");
}
public static void main(String[] args) {
ClassE.fun1();
ClassE.fun2();
}
}
运行结果:
ClassE静态方法块
调用静态方法1
调用静态方法2
注意:不管静态还是非静态的变量都可以被子类继承和覆盖(即父类中定义一个静态变量,可以通过子类进行调用)。
public class ClassB {
static int a = 1;
}
public class ClassA extends ClassB {
public static void main(String[] args) {
int z = ClassA.a;//合法操作
}
}
如果在子类中重写该静态变量,父类中该静态变量就会被隐藏。
2、作用在方法
静态方法,只要定义了类,不必建立类的实例就可使用。
public class ClassE {
public ClassE() {
}
static void fun1(){
System.out.println("调用静态方法1");
}
void fun2(){
System.out.println("调用非静态方法2");
}
public static void main(String[] args) {
ClassE.fun1();
ClassE classE = new ClassE();
classE.fun2();
}
}
静态方法的继承与静态变量的继承一致,可参照静态变量的做法进行操作。注意,静态方法中无法使用super关键字,所有有关于super关键字的一切操作都无实现。
3、静态内部类
关键字static不能修饰外部类,只能修饰内部类。
public class ClassD {
static class ClassE{
public ClassE() {
System.out.println("静态类构造方法");
}
void fun(){
System.out.println("静态类构造方法");
}
}
public static void main(String[] args) {
ClassE classE = new ClassE();classE.fun();
}
}
静态内部类的作用:为了降低包的深度,方便类的使用,静态内部类适用于包含类当中,但又不依赖与外在的类,只是为了方便管理类结构而定义。在创建静态内部类的时候,不需要外部类对象的引用。
静态内部类和非静态内部类区别:非静态内部类可以调用外部类变量,静态内部类不可以调用外部类非静态变量。
4、静态关键字Static对类初始化时调用代码顺序的影响
子Class继承含有static关键字父Class,构造子Class对象时,代码的执行顺序:
//父类
public class ClassI {
static int a = 1;//静态变量
int b = 1;//全局变量
static{
System.out.println("父类的静态代码块");
}
public ClassI() {
System.out.println("父类的构造方法");
}
}
//子类
public class ClassH extends ClassI{
static int c = 1;
int d = 1;//全局变量
static{
System.out.println("子类的静态代码块");
}
public ClassH() {
System.out.println("子类的构造方法");
}
public static void main(String[] args) {
ClassH classH = new ClassH();
}
}
父类的静态对象->子类的静态对象->父类全局变量声明和初始化->父类的构造函数->子类全局变量声明和初始化->子类的构造函数
二、Final
该关键字用于表明不可修改或者不可继承。可以作用于变量,方法,类
1、作用在类上面说明该类不可被继承
2、作用在方法上,说明在继承该类的子类不可修改该方法。
3、作用在变量上,说明该变量不可变(注意:在定义final类型的变量时,需要初始化该值,否则会报错)
关键字final对代码的调用顺序没有影响,用法也比关键字static简单。