public class Sub extends Super {
int argA;
static int argB;
int argC = 13;
{
System.out.println("动态语句块:Sub.argA = " + (argA = 11));
}
static{
System.out.println("静态语句块:Sub.argB = " + (argB = 12));
}
Sub(){
//super();
System.out.println("构造方法块:Sub.argC = " + argC);
print();
print(argB);
argA = 30;
} void print(int argA) {
System.out.println("sub.print(args)");
System.out.println(argA);
}
void print(){
System.out.println("sub.print()");
System.out.println(argA);
System.out.println(argB);
} public static void main(String[] args) {
System.out.print(new Sub().argA);
}
}class Super {
protected int argA = 21;
protected static int argB;
static{
argB = 22;
}
Super() {
print();
print(argA);
argA = 23;
} void print(int argA) {
System.out.println("super.print(args)");
System.out.println(argA);
}
void print() {
System.out.println("super.print()");
System.out.println(argA);
System.out.println(argB);
}
}
执行过程是这样的吗?
static int argB;
int argA;
int argC;
static{
System.out.println("静态语句块:Sub.argB = " + (argB = 12));
}
Sub(){
super();
argC = 13;
System.out.println("动态语句块:Sub.argA = " + (argA = 11));
System.out.println("构造方法块:Sub.argC = " + argC);
print();
print(argB);
argA = 30;
}
求解释。
******************************************************
静态语句块:Sub.argB = 12
sub.print()
0
12
sub.print(args)
21
动态语句块:Sub.argA = 11
构造方法块:Sub.argC = 13
sub.print()
11
12
sub.print(args)
12
30
**************************************************
分析:
main方法:new Sub().argA 首先,new 一个Sub对象,在new Sub对象时先new 其父类,所以先调用父类的静态块:argB = 22
此时,Super.argB = 22。再调用子类的静态块:argB = 12,此时,Sub.argB = 12。
输出1:
静态语句块:Sub.argB = 12
继续,创建对象,父类开始,变量初始化,Super.argA = 21,调用父类构造方法print();print(argA);argA = 23;
由于print()方法被子类重写,所以实际调用的是子类的print()方法
输出2:
sub.print()
0 //Subr.argA = 0;
12 //Sub.argB = 12
由于print(argA)方法被子类重写,所以实际调用的是子类的print(argA)方法,调用者是父类,传进去的是Super.argA = 21
输出3:
sub.print(args)
21 //父类传进去的21
之后,argA = 23,此时Super.argA = 23,Super.argB = 22。
父类创建好了之后,创建子类,变量初始化,argC = 13 后执行动态块
输出4:
动态语句块:Sub.argA = 11 //此时Sub.argA = 11,动态块中赋的值。
调用子类的构造方法:System.out.println("构造方法块:Sub.argC = " + argC);print();print(argB);argA = 30;
输出5:
构造方法块:Sub.argC = 13
调用子类print();print(argB);
输出6:
11 //Sub.argA
12 //Sub.argB
sub.print(args)
12 // 调用时传入的是Sub.argB
构造方法最后一句:argA = 30;此时Sub.argA = 30,Sub.argB = 12,Sub.argC = 13。
main方法中print了new Sub().argA
最后输出:
30 //Sub.argA = 30
Sub s = new Sub();
Super f = (Super) s;
System.out.println("**********************************");
System.out.println("Sub.argA : "+s.argA);
System.out.println("Sub.argB : "+s.argB);
System.out.println("Sub.argC : "+s.argC);
System.out.println("Super.argA : "+f.argA);
System.out.println("Super.argB : "+f.argB);
//System.out.print(f.argC);
}
protected static int argB; //设置为默认值 0 ;
static{
argB = 22; //初始化为 22
}接着加载子类Sub
static int argB;
int argC = 13;
{
System.out.println("动态语句块:Sub.argA = " + (argA = 11));
}
执行父类构造方法
Super() {
print();
print(argA);
argA = 23;
}子类构造方法
Sub(){
//super();
System.out.println("构造方法块:Sub.argC = " + argC);
print();
print(argB);
argA = 30;
}
int argA;
static int argB;
int argC = 13;
{ //这里应该是在new 一个Sub实例的时候才打印
System.out.println("动态语句块:Sub.argA = " + (argA = 11));
}
static{
System.out.println("------------Sub()静态数据模块.-----------") ;
System.out.println("静态语句块:Sub.argB = " + (argB = 12));
}
Sub(){
//super();
System.out.println("构造方法块:Sub.argC = " + argC);
print();
print(argB);
argA = 30;
} void print(int argA) {
System.out.println("sub.print(args)");
System.out.println(argA);
}
void print(){
System.out.println("sub.print()");
System.out.println(argA);
System.out.println(argB);
} public static void main(String[] args) {
System.out.print(new Sub().argA);
}
}class Super {
protected int argA = 21;
protected static int argB;
static{
System.out.println("------------Supper()静态数据模块.-----------") ;
argB = 22;
}
Super() {
System.out.println("------------Supper()构造函数 begin.-----------") ;
print();
print(argA);
argA = 23;
System.out.println("------------Supper()构造函数 end.-----------") ;
} void print(int argA) {
System.out.println("super.print(args)");
System.out.println(argA);
}
void print() {
System.out.println("------------Supper().print() begin .-----------") ;
System.out.println("Supper().argA = " + argA);
System.out.println("Supper().argA = " + argB);
System.out.println("------------Supper().print() end .-----------") ;
}
}结果:
------------Supper()静态数据模块.-----------
------------Sub()静态数据模块.-----------
静态语句块:Sub.argB = 12
------------Supper()构造函数 begin.-----------
sub.print()
0
12
sub.print(args)
21
------------Supper()构造函数 end.-----------
动态语句块:Sub.argA = 11
构造方法块:Sub.argC = 13
sub.print()
11
12
sub.print(args)
12
30
public class Sub extends Super {
int argA;//(12)
static int argB;//(4)
int argC = 13;//(13)
{
System.out.println("动态语句块:Sub.argA = " + (argA = 11));//(14)
}
static{
System.out.println("静态语句块:Sub.argB = " + (argB = 12));//(5)
}
Sub(){
//super();
System.out.println("构造方法块:Sub.argC = " + argC);//(15)
print();//(16)
print(argB);//(18)
argA = 30;//(20)
} void print(int argA) {
System.out.println("sub.print(args)");//(10),(19)
System.out.println(argA);//(10)Super.argA = 21,(19)Sub.argB=12
}
void print(){
System.out.println("sub.print()");//(8),(17)
System.out.println(argA);//(8),Sub.argA = 0,(17)Sub.argA=11
System.out.println(argB);//(8),Sub.argB = 12,(17)Sub.argB=12
} public static void main(String[] args) {
System.out.print(new Sub().argA);//(1),(21)Sub.argA=30
}
}class Super {
protected int argA = 21;//(6)
protected static int argB;//(2)
static{
argB = 22;//(3)
}
Super() {
print();//(7)
print(argA);//(9)
argA = 23;//(11)
} void print(int argA) {
System.out.println("super.print(args)");
System.out.println(argA);
}
void print() {
System.out.println("super.print()");
System.out.println(argA);
System.out.println(argB);
}
}
应该是2-5,1,然后6-21如果main函数在其他类(如Test类),执行顺序就是1-21
System.out.print(new Sub().argA);
当前对象的类型是Sub,传入父类构造函数的对象类型就是Sub
父类中print()等价于this.print(),此时this类型是刚才传入的对象类型Sub
这一点可以通过代码验证 Super() {
System.out.println(this.getClass());
print();
print(argA);
argA = 23;
}输出是class Sub
由于Sub覆盖了父类的方法,所以就会去执行父类的方法。如果换成System.out.print(new Super().argA);
那么this的类型就是Super,就会执行父类的方法
纠正下,笔误。
输出是class Sub
由于Sub覆盖了父类的方法,所以就会去执行Sub类的方法。
用this来描述,确实让我又更正些理解。因为我喜欢加this,理清了覆盖的问题。To 五哥
谢谢,描述的很清晰。To #1楼
感觉说法有点点问题。最后那些args打印出什么,我不关心。
主要关心的问题是,
问题一:为什么要覆盖,或者说会覆盖?
问题二:变量的声明和初始化跟构造方法之间顺序问题。顺便说下:本看到一大堆解释可能会扫的很快所以如有误解,很抱歉。
另外为了把静态的部分和产生对象分开,测试时可以用Class.forName()加载类,那些静态的部分只执行一次。
对于理解初始化过程会减低难度。