黑马程序员--Java基础学习笔记【继承、多态】

 

 ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------    

 

  • 继承 class 子类名extends 父类名{}

继承的好处:提高代码复用性;提高代码维护性;类之间产生关系,多态的前提。

继承的特点:只支持单继承;支持多层继承

子类可以使用父类所有的非私有成员

子类不能继承父类的构造方法,但是可以通过 super 访问

 

  • super 关键字父类存储空间的标识

在子类中,访问父类的成员, super.父类成员,不能写在静态里面

 

  • 继承中构造方法的关系

子类中所有的构造方法都默认会访问父类中空参数的构造方法

子类构造方法的第一行,有一条默认的隐式代码 super(); 调用父类空参数的构造方法

考虑到父类中成员变量的赋值情况,父类构造器没有对成员变量进行赋值,父类中重载的构造方法可以在子类中对 super() 传参数调用,即子类初始化之前要先完成父类初始化

 

*父类中没有默认的空参构造方法,子类构造方法中必须手动写 super() 指定参数列表

构造方法第一行,this() 和 super() 只能写一个

 

  • this 和 super 用法的区别

this 指本类对象的引用,super 父类存储空间标识

访问成员变量:

    this.成员变量   super.成员变量

访问构造方法

    this(); 用于本类构造方法之间互相调用

    super(); 子类的构造方法默认访问父类中空参的构造方法

访问成员方法

    this.成员方法   super.成员方法

 

  • 子父类中静态代码块、构造代码块、构造方法的执行顺序

class Fu {

    static {

        System.out.println("静态代码块Fu");

    }

    {

        System.out.println("构造代码块Fu");

    }

    public Fu() {

        System.out.println("构造方法Fu");

    }

}

 

class Zi extends Fu {

    static {

        System.out.println("静态代码块Zi");

    }

    {

        System.out.println("构造代码块Zi");

    }

    public Zi() {

        System.out.println("构造方法Zi");

    }

}

 

Zi z = new Zi();

  1. A.  静态随着类的加载而加载

  2. B.  静态代码块 -- 构造代码块 �C构造方法

  3. C.  只要有继承关系,先初始化父类的数据,再初始化子类数据

结果:

静态代码块Fu

静态代码块Zi

构造代码块Fu

构造方法Fu

构造代码块Zi

构造方法Zi


  • 继承中成员方法的关系

子类重写父类的方法,权限必须大于等于父类方法的权限,剩余方法声明部分须和子类一致

静态方法严格意义上没有重写,如果静态方法被覆盖,则子类中的方法也是静态的

 

  • final 关键字

修饰类,类成为最终类,不能被继承,没有子类

修饰成员方法,方法成为最终方法,不能被子类重写,可以调用

修饰成员变量,成员变量在堆内存中有默认值

    final 固定的是成员变量的手动赋值,而不是默认值

 

构造方法可以对成员变量初始化赋值,但是普通方法不可以对 final 成员变量赋值

因为构造方法是运行在对象建立过程中,普通方法调用时,对象已经建立完成了

 

  • 多态性

多态前提和体现:继承、方法重写,父类引用指向子类对象(反之不行)

多态的好处:程序的扩展性提高,父类固定不变子类是可以无限扩展的;维护性提高

多态的弊端:不能访问子类的特有功能

多态的意义:一个类型的引用在指向不同的对象时会有不同的实现;

同样一个对象,造型成不同的类型时,会有不同的功能。

 

  • 多态调用中编译和运行时期的特性:

    非静态成员变量、静态成员变量:

        编译时期,看父类中有没有这个变量,有编译成功,没有编译失败

        运行时期,运行的是父类中的成员变量

    非静态成员方法:

        编译时期,看父类中有没有这个方法,有编译成功,没有编译失败

        运行时期,运行的是子类重写后的方法

    静态成员方法:

        编译时期,看父类中有没有这个方法,有编译成功,没有编译失败

        运行时期,运行的是父类中的方法(所以说静态方法不能算方法的重写)

总结:除非静态的方法以外,编译和运行都看父类;

只有非静态的方法,编译看父类,运行看子类。

多态调用中,方法必走子类重写

编译看左边,运行看右边

Fu f     =     newZi();

 

  • 多态中的转型问题(孔子装爹案例)

向上转型:父类类型的引用指向子类对象;接口引用指向其实现类的对象

    Java编译器根据类型检查调用方法是否匹配

向下转型(强制转型):

可以通过强制类型转换将父类型变量转换为子类型变量,前提是该变量指向的对象确实是该子类类型。

也可以通过强制类型转换将变量转换为某种接口类型,前提是该变量指向的对象确实实现了该接口。

如果在强制转换过程中出现违背上述两个前提,将会抛出ClassCastException

instanceof 关键字

    为避免在强转中出现 ClassCastException 异常,可以通过 instanceof 关键字判断某个引用指向的对象是否为指定类型。

 

/*

 * 孔子装爹案例--多态中的转型问题

 */

publicclassKongZiDemo {

 

    publicstaticvoid main(String[] args) {

       // 多态调用:父类引用 = 子类对象

       // 子类提升为父类的类型,自动转换,向上转型

       KongZiDiekd = newKongZi();

       kd.teach();

       System.out.println(kd.age);

       System.out.println("-------");

 

       // 多态:不能使用子类特有功能

       // 使用子类特有,强制类型转换,已经提升为父类类型的子类对象,转回子类类型

       KongZik = (KongZi) kd; // 类型的向下转型

       k.playGame();

       System.out.println(k.age);

    }

}

 

class KongZiDie {

    intage = 70;

 

    publicvoid teach() {

       System.out.println("讲做官");

    }

}

 

class KongZi extends KongZiDie {

    intage = 40;

 

    publicvoid teach() {

       System.out.println("讲论语");

    }

 

    publicvoid playGame() {

       System.out.println("玩游戏");

    }

}


你可能感兴趣的:(继承,多态)