类的执行顺序(静态代码块,子父类等)知识点总结
1. 代码块
1.1 静态代码块
用static和{}声明的代码块,主要内容写在{}内部。
public class Test {
static {
System.out.println("Test类的静态代码块 1");
}
static {
System.out.println("Test类的静态代码块 2");
}
public static void main(String[] args) {
}
}
Test类的静态代码块 1
Test类的静态代码块 2
- 执行时机:第一次加载这个类的时候(不一定是生成实例,也有可能是调用静态变量或方法)。
- 一个类中可以有多个静态代码块,按书写顺序执行且都会执行,即写在上面的代码块先执行。
- 静态代码块有静态特性,不能访问普通变量或方法。
1.2 构造代码块
用{}声明的代码块,主要内容写在{}内部。
public class Test {
{
System.out.println("Test类的构造代码块 1");
}
{
System.out.println("Test类的构造代码块 2");
}
public static void main(String[] args) {
new Test(); // 加载一个Test类的实例
}
}
Test类的构造代码块 1
Test类的构造代码块 2
- 执行时机:加载一个类的实例的时候。
- 可以同时有多个构造代码块,按书写顺序执行且都会执行,即写在上面的代码块先执行。
- 构造代码块在编译生成class文件之后,会把其中所有的代码放到所有的构造方法的上面。
1.3 构造函数
常见的构造函数,没有返回类型,方法名就是类名。
public class Test {
public Test(){
System.out.println("Test类的构造函数 1");
}
public Test(String name){
System.out.println("Test类的构造函数 2");
}
public static void main(String[] args) {
new Test();
}
}
Test类的构造函数 1
- 执行时机:创建对象实例且调用到对应方法时。
- 可以有多个构造方法,但是参数列表必须不同。
1.4 代码块的执行顺序
执行顺序是:静态代码块 > 构造代码块 > 构造函数。
public class Test {
static {
System.out.println("Test类的静态代码块 1");
}
{
System.out.println("Test类的构造代码块 1");
}
public Test(){
System.out.println("Test类的构造函数 1");
}
public static void main(String[] args) {
System.out.println("准备执行new Test()");
new Test();
}
}
Test类的静态代码块 1
准备执行new Test()
Test类的构造代码块 1
Test类的构造函数 1
看到这里之后,请试着解决下面这道题:
https://www.nowcoder.com/questionTerminal/3910188b1259470a9bb7109885ed48c8?toCommentId=5821133
2. 子类和父类
2.1 创建的执行顺序
一律父类先于子类,静态先于动态。无特殊情况(指用super主动调用方法),父类一律是调用无参构造函数。
如果要在子类构造函数中调用super()方法,则必须要将其放在第一行,所以父类一定先于子类执行。
public class T {
public static void main(String[] args) {
new Son();
}
}
class Father {
static {
System.out.println("父类的静态代码块");
}
{
System.out.println("父类的构造代码块");
}
public Father(){
System.out.println("父类的构造方法");
}
}
class Son extends Father{
static {
System.out.println("子类的静态代码块");
}
{
System.out.println("子类的构造代码块");
}
public Son(){
System.out.println("子类的构造方法");
}
}
父类的静态代码块
子类的静态代码块
父类的构造代码块
父类的构造方法
子类的构造代码块
子类的构造方法
2.2 子类新建父类的实例
静态变量和方法一律遵循编译看左边,运行也看左边的原则。
非静态变量和方法一律遵循编译看左边,运行看右边的原则,
- 当你编译的时候,能不能通过编译,主要看你左边的类是否是右边的类或者它的继承,是就能通过编译。且编译时父类只能调用
- 当你运行的时候,无论你编译时左边的是父类还是子类,一律调用右边所创建的实例的对应方法。
public class T {
public static void main(String[] args) {
Son son = new Son();
Father father = new Son();
//你不能通过实例son来调用变量,只能用类名Son
System.out.println(Son.str); // 子类的静态变量,
System.out.println(Father.str); //父类的静态变量
son.func(); // 子类的方法
father.func(); // 子类的方法
//father.func2(); 无法通过编译,编译时Father类并没有func2()这个方法
}
}
class Father {
public static String str = "父类的静态变量";
public void func(){
System.out.println("父类的方法");
}
}
class Son extends Father{
public static String str = "子类的静态变量";
public void func(){
System.out.println("子类的方法");
}
public void func2(){
System.out.println("子类的方法2");
}
}
参考材料
Java之static静态代码块 - 随风而行- - 博客园
https://www.cnblogs.com/Heliner/p/10524699.html
Java中静态代码块、构造代码块、构造函数、普通代码块 - YSOcean - 博客园
https://www.cnblogs.com/ysocean/p/8194428.html
【Java学习笔记】如何理解java中的“编译看左边,运行看右边”_名侦探张六儿的博客-CSDN博客
https://blog.csdn.net/u012198209/article/details/80064049