代码Parent和Sub进行讲解
public class Parent { private static final String name; public Parent() { System.out.println("父类构造方法"); } static{ name="hello parent"; System.out.println("父类静态块1"); } static{ System.out.println("父类静态块2"); } { System.out.println("父类非静态块1"); } { System.out.println("父类非静态块2"); } }
public class Sub extends Parent{ public Sub() { System.out.println("子类构造方法"); } static{ System.out.println("子类静态块"); } { System.out.println("子类非静态块"); } }
public class Test { public static void main(String[] args) { Parent s1=new Sub(); Parent s2=new Sub(); } }
运行结果:
父类静态块1
父类静态块2
子类静态块
父类非静态块1
父类非静态块2
父类构造方法
子类非静态块
子类构造方法
父类非静态块1
父类非静态块2
父类构造方法
子类非静态块
子类构造方法
结果:
父类静态代码块
子类静态代码块
----- 类加载时只调用一次
父类代码块
父类构造方法
子类代码块
子类构造方法
-----每次创建一个对象就调用一次
结论:
static修饰的代码块属于静态代码块属于类,加载时只调用一次;
非static修饰的代码块属于对象,每次创建对象都会运行非static修饰的代码块。
因为静态代码优先于非静态的代码,被static修饰的成员都是类成员,会随着JVM加载类的时候加载而执行,
没有被static修饰的成员也被称为实例成员,需要创建对象才会随之加载到堆内存,所以静态的会优先非静态的先执行
以上主要讲解的是代码块的执行顺序,读者可能不易理解的final和static的使用,以下是对final的static的简单总结,辅助读者理解
static:
被static修饰的方法和属性独立于该类的任何对象 不需要创建对象就可以进行访问
使用static修饰的方法和属性可以直接通过类进行调用
static修饰代码块,类加载时候就会执行
static修饰的变量 :内存中只有一份,不需要创建对象就可以进行调用,只要属于这个类创建的对象,都会共享这个变量
成员变量 : 只有在对象创建之后才能被调用,每一个对象都会拷贝一份,每个对象只能访问自己的成员变量
static修饰方法:又称静态方法,属于类,不需要创建对象就可以调用。静态方法不能调用非静态方法,内部不能使用this、super
static可以直接创建代码块
例如:
static { //自己的逻辑 }
static修饰的静态代码块在一个类中可以有多个,加载的顺序按照书写的顺序。虚拟机只会在加载类的时候对代码块加载一次
final:
final 修饰类 :类不能被继承、final修饰的类中的方法,默认全是final修饰的
父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的
final修饰方法 : 使用final修饰的方法,子类是不能进行重写的
final修饰的变量,一旦给了值之后,是不能被修改的
注意:final变量定义的时候,可以先声明,而不给初值
这种变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化
例如:
public class HelloWord{ private final int E; public HelloWorld(){ E=10; //这样也是可以的,不会报编译错误,而且运行也正常 } //后期使用,E=10如果被修改会报错 }