static 和 final
static
static关键字简而言之就是:方便在没有创建对象的情况下使用类当中的方法和属性
非静态方法可以调用静态的方法和属性,但反之是不可以的
使用static修饰的方法和属性只会在类加载的时候实例化一次,类和对象都共用这一个实例
由于上一个特性,可以调用static代码块来优化程序性能
代码实例1:
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
控制台输出
base static test static base constructor test constructor
入口方法创建test对象的时候,程序加载Test类,但是Test类继承自Base类,所以程序转而先加载Base类,static代码块在类加载时最先被调用,所以Base的静态代码块被先调用,而后调用Test的静态代码块;类加载完成后,调用子类构造方法,但子类构造方法默认先调用父类构造方法,所以先打印了父类构造方法代码块,后打印了子类构造方法代码块。
代码实例2:
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
控制台输出
test static
myclass static
person static
person Test
test constructor
person Myclass
myclass constructor
调用入口函数main之前需先加载Test类,所以先执行Test类的静态代码块(打印test static);入口函数创建MyClass对象前需加载MyClass类,MyClass类继承自Test类,但Test类已经被加载所以不再再次加载,故将直接执行Myclass的静态代码块(打印myclass static);加载完类后,调用子类Myclass的构造方法,但首先仍需先生成父类的对象,所以父类Test的Person属性会先生成,此时需要加载Person类,所以调用person类的静态代码块(打印person static);父对象Test类person属性时会调用Person类的构造方法(打印person Test),而后调用父对象Test的构造方法(打印test constructor),此时父对象创建完成;而后开始完成子对象自身的操作,子对象的person属性调用person的构造方法(打印person Myclass),而后调用子对象的构造方法(打印myclass constructor)
final
修饰类
使用final修饰类的时候,代表这个类永远无法被继承,同时该类中的所有成员方法都会被隐式制定为final方法
修饰方法
使用final修饰方法的时候,代表该方法被锁定,无法被后代继承的成员所修改
修饰变量
使用final修饰变量的时候,如果是基本类型的变量,那么该变量在初始化后便不可更改;如果是引用类型的变量,那么在初始化后将不能指向另一个对象,但是该引用类型的对象内的属性仍旧可以更改