Thinking in Java_继承

一、 父类的初始化

子类(派生类)创建一个对象时,就包含了对父类(基类)对象的创建,从外部看,父类的对象就已经被封装到子类的对象中。因此,父类能够正确的初始化,通过子类在创建子类对象,调用子类构造方法时,java编译器会自动对父类构造方法的调用。例如:

 1、无参构造方法的调用

class A {
A(){
System.out.println("A.A()");
}
}
class B extends A{
B(){
System.out.println("B.B()");
}
}
public class C extends B{
C() {
System.out.println("C.C()");
}
public static void main(String[] args) {
C c = new C();
}
}

结果:

A.A()
B.B()
C.C()

Note: 

(1)、注意调用的顺序,根父类最先调用,其次才是它的子类。

(2)、即使子类C没有创建无参构造方法,编译器也会默认生成C类的构造方法,并完成对A类、B类构造方法的调用。

2、有参构造方法的调用

class A {
A(int i){
System.out.println("A.A()");
}
}
class B extends A{
B(int i){
super(i);            //如果此处没有对父类的显示调用,就会提示出错:Implicit super constructor A() is undefined. Must explicitly invoke another constructor
System.out.println("B.B()");
}
}
public class C extends B{
C() {
super(1);       //同理,如果没有显示调用父类,提示:Implicit super constructor B() is undefined. Must explicitly invoke another constructor
System.out.println("C.C()");
}
public static void main(String[] args) {
C c = new C();
}
}

结果:

A.A()
B.B()
C.C()

Note:对有参构造方法的调用时,必须通过super()显示的调用父类构造方法。

二、上溯造型(upcasting)

上溯造型:源于继承关系图,基类在顶部,派生类向下发展。它是一种安全的类型转换:从派生类到基类的转变。一个方法的参数是基类句柄,若派生类对象调用此方法时的参数为派生类句柄,则传入的参数自动转化为基类句柄,并执行方法体。但是,如果该方法体中有覆盖,则不会出现向基类的转变。code:

class Animal{
public void speak() {
System.out.println("Animal.speak()");
}
// public static void upcasting(Animal animal) {        //该方法也可以加到基类,效果一样
// animal.speak();
// }
}
class Dog extends Animal{
public void eat() {
System.out.println("Dog.eat()");
}
// public void speak() { //若子类重写该方法,则不会出现类型的转变:结果为:Animal.speak()
// System.out.println("Dog.speak()");    Dog.speak()
// }    Dog.speak()
}
public class Test {
public static void upcasting(Animal animal) {
animal.speak();
}
public static void main(String[] args) {
Animal animal = new Animal();
upcasting(animal);
Dog dog1 = new Dog();
upcasting(dog1);
Animal dog2 = new Dog();
upcasting(dog2);
}
}

结果:

Animal.speak()
Animal.speak()
Animal.speak()

Note:上溯造型可以理解为:派生类通过继承后本身就包含了基类的所有元素,也属于基类的一种,可以直接访问从基类继承的现有成员,但是属于派生类特有的方法却不能通得到转变。

三、继承的初始化

一个继承类的初始化顺序:

1、首先,将继承类的父类、上一级父类(如果有的话)等依次装载,最后是继承类,这个过程中,执行的是根父类static成员的初始化,然后是下一级的static成员初始化,以此类推,最后是继承类的static成员。

2、所有相关类装载完后,根据创建的继承类对象,首先将基本数据类型设为默认值,对象句柄设为null,然后调用根父类的构造方法完成初始化,其次是下一级,以此类推,最后是继承类的构造方法调用。

3、构造方法调用完后,然后按照程序中本来的顺序继续执行初始化。

for example:

class Insect {
int i = 9;
int j;
Insect() {
prt("i = " + i + ", j = " + j);
j = 39;
}
static int x1 =
prt("static Insect.x1 initialized");
static int prt(String s) {
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect {
int k = prt("Beetle.k initialized");
Beetle() {
prt("k = " + k);
prt("j = " + j);
}
static int x2 =
prt("static Beetle.x2 initialized");
static int prt(String s) {
System.out.println(s);
return 63;
}
public static void main(String[] args) {
prt("Beetle constructor");
Beetle b = new Beetle();
}

结果:

static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9, j = 0
Beetle.k initialized
k = 63
j = 39


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值