定义A、B、C、D四个类,B、C继承A,D继承B
class A{
public int a;
private int b;
protected int c;
// 两个构造方法
public A() {
a = 1;
b = 2;
c = 3;
System.out.println("父类默认构造方法");
}
public A(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
System.out.println("父类重载构造方法");
}
public void myPrint1() {
System.out.println("父类_1");
}
public void myPrint2() {
System.out.println("父类_2");
}
}
// 子类
class B extends A{
public int d;
// 构造函数
public B() {
super();
d = 3;
System.out.println("子类默认构造方法");
}
public B(int a, int b, int c, int d) {
super(a, b, c);
this.d = d;
System.out.println("子类重载构造方法");
}
public void myPrint1() {
System.out.println("子类B_1");
}
public void printB() {
System.out.println("a = "+this.a+"; c="+this.c);
}
public void printP(){
super.myPrint1();
}
}
// 子类
class C extends A{
public int a; // 覆盖父类成员变量
public C() {
super();
}
public C(int a) {
super();
this.a = a;
}
public void myPrint1() {
System.out.println("子类C_1");
}
public void printC() {
System.out.println("子类a = "+this.a+"; 父类a="+super.a);
}
}
// “孙”子类
class D extends B{
}
子类在新建对象时,首先调用父类的构造方法,然后调用自己的构造方法。其中super()可不写,但是为了避免不必要的麻烦还是写上。
B B1 = new B();
/*
父类默认构造方法
子类默认构造方法
*/
B B2 = new B(5,4,3,2);
/*
父类默认构造方法
子类重载构造方法
*/
1、子类可以继承父类public和protected修饰的成员变量和成员方法。
B B1 = new B(3, 4, 5);
System.out.println(B1.a); // 输出:3
System.out.println(B1.c); // 输出:5
System.out.println(B1.d); // 输出:6
//System.out.println(B1.b); // 报错(java.lang.Error:Unresolved compilation problem)
2、 子类覆盖父类的成员变量
C C1 = new C();
C C2 = new C(5);
C1.printC(); // 输出:子类a = 0; 父类a=1
C2.printC(); // 输出:子类a = 5; 父类a=1
System.out.println(C2.a); // 输出:5
1、非同名方法
B B1 = new B(3, 4, 5, 6);
B1.myPrint2(); // 输出:父类_2
2、同名方法:子类覆盖父类方法
B B1 = new B(3, 4, 5, 6);
B1.myPrint1(); // 输出:子类B_1
如何调用父类被覆盖的方法,类似成员变量,在类B的定义中,定义一个新的函数,使用super关键词。
public void printP(){
super.myPrint1();
}
B1.printP(); // 输出:父类_1
1、子类转父类–>向上转型
无需转换,生成的对象类别为子类,只能调用父类和子类同时拥有的变量和成员方法。
A A1 = new B(3, 4, 5, 6);
System.out.println(A1.getClass()); // 输出:class mytest.B
A1.myPrint1(); // 输出:子类B_1,调用了子类的方法
A1.myPrint2(); // 输出:父类_2
// A1.printB(); // 报错(java.lang.Error:Unresolved compilation problem)
// System.out.println(A1.d); // 报错(java.lang.Error:Unresolved compilation problem)
A A2 = new C(7);
System.out.println(A2.a); // 输出:1,却不是7
System.out.println(A2.c); // 输出:3
注意:存在覆盖的情况时,成员方法调用子类的,而成员变量却是父类的值。子类的同名属性被隐藏,父类的同名方法被覆盖。简单点来说,用子类来创建父类对象只是将父类被覆盖的方法替换为子类的方法。
2、将A1,A2进行强制转换–>向下转型
A A10 = new B(3, 4, 5, 6);
B A1 = (B) A10;
System.out.println(A1.getClass()); // 输出:class mytest.B
A1.myPrint1(); // 输出:子类B_1,调用了子类的方法
A1.myPrint2(); // 输出:父类_2
A1.printB(); // 输出:a = 3; c=5
System.out.println(A1.d); // 输出:6
A A20 = new C(7);
C A2 = (C) A20;
System.out.println(A2.a); // 输出:7
System.out.println(A2.c); // 输出:3
对比1和2中的变化,总结来说相当于完全转换成子类,相当于"B A1 = new B();“和"C A2 = new C();”。
3、 父类强制转子类
非法操作,报错:java.lang.ClassCastException。
A A1 = new A();
B B1 = (B) A1; // 报错( java.lang.ClassCastException:mytest.A cannot be cast to mytest.B)
4、不同子类相互转换
非法操作,报错:java.lang.Error: Unresolved compilation problem。
B B1 = new B();
C C1 = (C) B1; // 报错(java.lang.Error: Unresolved compilation problem)
B B2 = new A(); // 报错(java.lang.Error: Unresolved compilation problem)
可以进行转换,但是只有两个所共有的成员方法,若有重复的以赋值对象的为准。成员变量是父类的值。
A B2 = new B();
C C2 = new C(5);
B2 = C2;
System.out.println(B2.getClass()); // 输出:class mytest.C
B2.myPrint1(); // 输出:子类C_1
// B2.printB(); // 报错(java.lang.Error: Unresolved compilation problem)
// B2.printC(); // 报错(java.lang.Error: Unresolved compilation problem)
当直接父类和祖父类存在同名成员变量和成员方法时,采用就近原则,调用直接父类的。
D D1 = new D();
System.out.println(D1.a); // 输出:1
D1.myPrint1(); // 输出:子类B_1
D1.myPrint2(); // 输出:父类_2