先放一段代码,通过修改参数来理解以下四个问题:
1.父类子类混合创建一个新对象的构造逻辑(多态性及动态绑定)
2.this.方法实质
3.静态方法的隐藏(成员变量)
4.非静态方法的覆盖
对1的解释:声明父类新建子类对象的与常规新建对象的区别(A p = new B()):
先看如下代码,A是B的父类,m()被覆盖。
class A {
int x=1;//被隐藏
A() {
System.out.println("这里构建了一个父类对象");
}
void m() {//被覆盖
System.out.println("这里是父类的实例方法m()");
}
void m1() {
this.m();
this.m2();
this.m3();
System.out.println(this.x);
System.out.println("这里是父类的实例方法m1()");
}
static void m2(){//被隐藏
System.out.println("这里是父类的静态方法m2()");
}
void m3() {//未被覆盖
System.out.println("这里是父类的实例方法m3()");
}
}
class B extends A {
int x=2;
B() {
System.out.println("这里构建了一个子类对象");
}
void m() {
System.out.println("这里是子类的实例方法m()");
}
static void m2(){
System.out.println("这里是父类的静态方法m2()");
}
}
public class Test1 {
public static void main(String[] args) {
A a = new A();
a.m1();
System.out.println();
B b = new B();
b.m1();
System.out.println();
A c = new B();
c.m1();
}
}
输出结果为:
这里构建了一个父类对象
这里是父类的实例方法m()
这里是父类的静态方法m2()
这里是父类的实例方法m3()
1
这里是父类的实例方法m1()
这里构建了一个父类对象
这里构建了一个子类对象
这里是子类的实例方法m()
这里是父类的静态方法m2()
这里是父类的实例方法m3()
1
这里是父类的实例方法m1()
这里构建了一个父类对象
这里构建了一个子类对象
这里是子类的实例方法m()
这里是父类的静态方法m2()
这里是父类的实例方法m3()
1
这里是父类的实例方法m1()
可以看出:
构造顺序为
父类属性初始化-》父类构造方法-》子类属性初始化-》子类构造方法
而且实际会构造的对象要看声明的类型,如果是子类就是子类的。
其中A c = new B();
构建顺序为先构建父类,再构建子类。但只能调用被子类覆盖的方法,而不能调用子类独用的方法。(在B中设计一个父类没有的m3方法,然后用c.m3()调用,发现报错,m3()未被定义。哪怕m3()改为静态方法也不行)
也就是说只多了一个被覆盖的方法,其他没影响。
而且this指的就是this这个词自己所在的类,而非网上部分文章说的是建立的对象(new后面的)的类,只是被覆盖的方法除外,隐藏了没用。而且A中的this去掉也没有影响。
父类中被覆盖的方法在父类中无法调用,在子类中可以用super调用,其他地方可以通过只建立父类对象直接调用,用子类间接调用只能找子类里用的super方法的。
被隐藏的变量和静态方法可以在父类中被直接调用,其他和覆盖一致。
下面可以利用另一端代码进行练习测试:
class A{
int x = 1;//被隐藏
void print(){//被覆盖
System.out.println("这里是父类方法,x="+x);//父类A的方法中访问的变量必然是A类或A的父类的,不可能访问B类的。
m();//父类A的方法中调用的实例方法m()是子类B的,由于发生了覆盖
}
void m(){//被覆盖
System.out.println("这里是父类的实例方法m()");
}
static void m2(){//被隐藏
System.out.println("这里是父类的静态方法m2()");
}
}
class B extends A{
int x = 2;
void print(){
System.out.println("这里是子类方法,x="+x);//子类方法访问的变量是子类对象的(当然条件是子类中声明了这个变量)
System.out.println("这里是子类方法,super.x="+super.x);//super.x是父类对象的
super.print();//调用父类的print()方法
m();//调用本对象的m()方法
}
void m(){
System.out.println("这里是子类的实例方法m()");
}
static void m2(){
System.out.println("这里是子类的静态方法m2()");
}
static void m3(){//静态与否都没用
System.out.println("这里是子类的实例方法m3()");
}
}
public class Test{
public static void main(String []s){
A p = new B();
System.out.println(p.x);//通过引用变量p来访问变量或静态方法,要看p的声明类型。所以x是A类的。
p.m2();//同上。静态方法m2()是A类的。
p.print();//通过引用变量p来访问实例方法,要看p指向的对象的实际类型。由于覆盖,调用的print()方法是子类的。
p.m3();//报错The method m3() is undefined for the type A
}
}