package com.xxx.ll
class Base{
{
System.out.println("Base 普通代码块");
}
static {
System.out.println("Base 静态代码块");
}
Base(){
System.out.println("Base 构造方法代码块");
}
}
class Parent extends Base{
int i = 0;
int j = 3;
{
System.out.println("Parent 普通代码块");
}
static{
System.out.println("Parent 静态代码块");
}
public Parent(){
System.out.println("Parent 构造方法代码块");
}
void out(){
System.out.println(i+"====="+j);
}
}
class Child extends Parent{
int i = 3;
int j = 0;
{
System.out.println("Child 普通代码块");
}
static{
System.out.println("Child 静态代码块");
}
public Parent(){
System.out.println("Child 构造方法代码块");
}
void out(){
System.out.println(i+"#####"+j);
}
}
public class test{
public static void main(Sting[] args){
Parent p = new Parent;
p.out();
System.out.println(p.i+"$$$$"+p.j);
}
}
这道题主要考察静态代码块、非静态代码块、继承。
首先介绍一下代码块:代码块就是用‘{ }’包裹的一块代码,如果在{}外加static就是静态代码块。
然后介绍一下类的装载步骤:
在Java中类装载器把一个类装入Java虚拟机中要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分为校验、准备和解析三步,除了解析外,其他步骤都是严格按照顺序来完成的,各个步骤的主要工作如下:
装载:查找导入类或接口的二进制数据;
链接:执行下面的校验、准备和解析步骤,其中解析的步骤是可以选择的;
校验:检查导入类或接口的二进制数据的正确性;
准备:给类的静态变量分配并初始化存储空间;
解析:将符号引用转为直接引用;
初始化:激活类的静态变量的初始化的Java代码和静态Java代码块;
初始化类中的属性是静态代码块的常用用途,但只能使用一次。
所以静态代码块的优先级要高于非静态代码块和构造方法代码块,同时在一个类中非静态代码块优先级高于构造方法。
然后介绍一下继承:
继承是从已有的类中派生出新的类,新的类吸收已有类的数据属性和行为,并能扩展新的能力。
在上面程序中,子类Child继承了父类Parent 并且对于父类的方法进行了重写。
所以当p在调用out()的时候 用的是子类的Child的out()方法。
如果子类Child 没有对父类的out()方法进行重写,那么对象p用的将是父类Parent的out()方法
正如上面所说,因为p调用的是子类Child的out()方法,所以输出的结果中i、j是Child类所赋的值。
因为p是父类Parent的实例对象,所以p中i、j的值一定是Parent中的i、j值。
综上所述:
a类继承b类 a类b类各有一个静态代码块、普通代码块、构造函数
它们的执行顺序为:
父类静态代码块
子类静态代码块
父类非静态代码块
父类构造方法代码块
子类非静态代码块
子类构造方法代码块
注意:子类的构造方法,不管这个构造方法带不带参数,默认它都会先去寻找父类不带参数的构造方法,如果父类没有不带参数的构造方法,那么子类必须使用super关键字来调用父类参数的构造方法,否则编译不通过。
本博客所有内容仅供个人学习使用,如有侵权,敬请谅解。