Java学习(继承)——类,超类,子类(二)

目录

理解方法调用

阻止继承:final类和方法

强制类型转换

抽象类

受保护访问


理解方法调用

  • 假设要调用x.(args),隐式参数为类C的一个对象。下面时调用过程的详细描述

    1. 编译器查看对象的声明类型和方法名

    2. 接下来编译器要确定方法调用中提供的参数类型。因为可能存在多个方法方法名一样,但是参数不一样,编译器需要根据参数时字符串型还是其他类型,来选择正确的方法来调用

    3. 如果是private方法,static方法,final方法或者构造器,那么编译器将准确的直到要调用哪个方法。这叫做静态绑定,与此对应的时,如果要调用的方法依赖于隐式参数的实际类型,那么必须在运行时使用动态绑定。

    4. 程序运行并采用动态绑定时,虚拟机必须调用x索引用的那个类的实际类型对应的那个方法。假设x的实际类型时D,它是C类的子类,如果在D类定义了这个方法那么就会调用D类的这个方法,否则就在D类的父类C类中寻找此方法,以此类推。

      • 每次调用方法都会完成这个搜索,时间开销很大,因此虚拟机为每个类计算了一个方法表,其中列出来所有的方法的签名(方法的签名:方法的名字和参数列表)和要实际调用的方法,虚拟机仅需要查找这个表就行了

  • 动态绑定的重要特性:

    无需对现有的代码进行修改就能对程序进行扩展。假设有一个新类Executive,并且变量e有可能引用这个类的对象,我们不需要对e.getSalary()的代码重新编译,如果e恰好引用了一个Excutive类的对象,就会自动的调用Excutive类的getSalary方法

  • 注意:在重写一个方法时,子类的方法可见性不能低于超类的,特别的如果超类的方法的可见性时public那么子类的方法也必须声明为public

阻止继承:final类和方法

  • 有时候我们希望阻止人们利用某些类来定义子类,不允许扩展的类称为final类,如果在定义类的时候使用了final修饰符,就代表这个类是final类

  • 例如如果不想让人们派生Excutive类就在定义Excutive类的时候定义下面的语句

    public final class Excutive extends Manager{
        ...
    }
  • 类中的某个方法也可以声明为final这样子类就不能重写这个方法了

    • 注意final类的方法自动变为final方法

  • 将方法声明为final的主要原因:确保不会在子类中改变语义。例如:Calender类中的getName和setName都设置为final,这表明了只允许Calender类的设计者负责Date类与日历状态的转化,而不允许子类来添乱。同样的String类也是final类型,意味着不允许任何人定义String的子类。换一句话说就是,如果有一个String引用,它引用的一定是一个String对象,而不可能是其他类的对象。

强制类型转换

  • 正像有时候需要将浮点数转换为整数一样,有时候也需要将一个类的对象引用转换为另一个类的对象引用

  • 语法:需要将目标类名用圆括号括起来,并放在需要转换的对象引用之前就可以了

    Manager boss=(Manager)staff[0];
  • 注意:将一个子类引用赋值给超类变量这样是允许的,但将一个超类引用赋值给一个子类变量,这样不可以staff是Employee类型的

    Manager boss=(Manager)staff[0]//Error

    因为不是所有的员工都是经理

  • 所以在此之前应该使用instanceof操作符来查看能否成功的转换

    if(staff[0] instanceof Manager){
        boss=(Manager)staff[1];
        ...
    }
  • 强制类型转换注意点:

    • 只能在继承层次内进行强制类型转换

    • 在将超类转换为子类之前,应当使用instanceof进行检查

抽象类

  • abstract修饰符可以用来修饰类或者方法,修饰方法就是抽象方法,修饰类就是抽象类

  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类

  • 对于抽象类:

    • 不能使用new关键字来创建对象,它是用来让子类继承的

  • 对于抽象方法:

    • 只有方法的声明没有方法的实现,它是用来让子类实现的。例如Person类下有两个子类分别是,Student类,和Employee类,在两个子类中都有一个歌坛getDescription()方法,这个方法返回对一个人的简短描述,但在Person类中处理这个人的姓名别的什么都不能提供,这时就让Person.getDescription返回空,但更好地办法时让其声明为abstract

  • 除了抽象方法外,抽象类还可以包含具体的字段和方法,像Person类还有一个name的字段,和一个getName()的方法

  • 可以定义一个抽象类的变量,但是这样的一个变量只能引用非抽象子类的对象

    Person a=new Studnet();
  • 子类继承抽象类,那么就必须实现抽象类没有实现的抽象方法,否则该子类也应该定义为抽象类

  • 抽象类中也有构造函数,而且抽象类的构造函数是起作用的,而且在实例化子类对象时首先构调用的是抽象类的构造函数,再调用子类的构造函数

受保护访问

  • 有些时候,可能希望超类中的某个方法只允许子类进行访问,或者更少见的,只允许子类中的某个方法访问超类的某个字段,为此,需要将这些类或者字段声明为受保护的(protected)

  • 在Java中只允许同一个包中的类访问保护字段现在有一个Employee的子类,这个子类在不同的包中,这个子类的方法只能查看自己对象的hireDay字段,而不能查看其他Employee对象的字段,有了这个机制就能避免滥用保护机制,不能通过派生子类来访问受保护字段

  • 受保护的方法更具有保护意义,将方法声明为protected这样就可以让子类正确的访问,而其他类不行

  • Java的三个访问控制修饰符:

    • 仅对本类可见private

    • 对外部完全可见public

    • 对本包和所有子类可见protected

    参考书籍:Java核心技术 卷1(原书第11版)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Iron_Sp-man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值