zoukankan      html  css  js  c++  java
  • 5. 继承

    5. 继承

    利用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用(继承)这些类的方法和域。

    反射是指在程序运行期间发现更多的类及其属性的能力。

    5.1 类、超类和子类

    5.1.1 定义子类

    public class Student extends Person{
        //方法和域
    }
    

    关键字extends表名正在构造的新类派生于一个已存在的类。已存在的类成为超类、基类或父类;新类称为子类、派生类或孩子类。

    5.1.2 覆盖方法

    在子类中可以增加域、增加方法或覆盖超类的方法,但是绝对不能删除集成的任何域和方法。

    在Java中使用关键字super调用超类的方法。

    5.1.3 多态

    多态:同一类的对象收到相同消息时,会得到不同的结果。而这个消息是不可预测的。多态,顾名思义,就是多种状态,也就是多种结果。

    多态性是一种通过多种状态或阶段描述相同对象的编程方式。它的真正意义在于:实际开发中,只要关心一个接口或基类的编程,而不必关心一个对象所属于的具体类。

    在Java程序设计语言中,对象变量是多态的。一个Student变量既可以引用一个Student类对象,也可以引用一个Student类的任何一个子类的对象。

    在Java中,子类数组的引用可以转换成超类数组的引用,而不需要采用强制类型转换。

    5.1.4 阻止继承:final类和方法

    不允许扩展的类被称为final类。如果在定义类的时候使用了final修饰符就表名这个类是final类。

    5.1.5 抽象类

    如果自下而上在类的继承层次结构中上移,位于上层的类更具有通用性,甚至可能更加抽象。

    使用abstract关键字实现抽象类。

    建议尽量将通用的域和方法放在超类中。

    扩展抽象类的两种选择:在抽象类中定义部分抽象类方法或不定义抽象类方法,这样就必须将子类也标记为抽象类;定义全部的抽象方法。

    • 类即使不含抽象方法,也可以将类声明为抽象类。
    • 抽象类不能被实例化。也就是说,如果将一个类声明为abstract,就不能创建这个类的对象。

    5.1.6 受保护访问

    • 仅对本类可见--private
    • 对所有类可见--public
    • 对本包和所有子类可见--protected
    • 对本包可见--默认,不需要修饰符

    5.2 Object:所有类的超类

    Object类是Java中所有类的始祖,在Java中每个类都是由它扩展而来的。

    如果没有明确地指出超类,Object就被认为是这个类的超类。

    可以使用Object类型的变量引用任何类型的对象:

    Object obj = new Employee("Hello World", 35000);
    

    Object类型的变量只能用于作为各种值得通用持有者。要想对其中的内容进行具体的操作,还需要清楚对象的原始类型,并进行响应的类型转换:

    Employee e = (Employee)obj;
    

    所有的数组类型,不管是对象数组还是基本类型的数组都扩展了Object类。

    5.2.1 equals方法

    Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断两个对象是否具有相同的引用

    在子类中定义equals方法时,首先调用超类的equals。如果检测失败,对象就不可能相等。如果超类中的域都相等,就需要比较子类中的实例域。

    5.2.2 相等测试与继承

    Java语言规范要求equals方法具有以下特性:

    • 自反性:对于任何非空引用x,x.equals(x)应该返回true
    • 对称型:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true
    • 传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true
    • 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果
    • 对于任意非空引用x,x.equals(null)应该返回false

    如果子类能够拥有自己的相等概念,则对称型需求将强制采用getClass进行检测

    如果由超类决定相等的概念,那么就可以使用instanceof进行检测,这样可以在不同子类的对象之间进行相等的比较。

    Java核心技术给出的equals方法建议:

    1. 显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量

    2. 检测this与otherObject是否引用同一个对象:if(this == otherObject) return true;

    3. 检测otherObject是否为null,如果为null,返回false。这项检测是很必要的。if(otherObject == null) return false;

    4. 比较thisotherObject是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测:if(getClass != otherObject.getClass()) return false;

      如果所有的子类都拥有统一的语义,就是用instanceof检测:if(!(otherObject instanceof ClassName)) return false;

    5. otherObject转换为相应的类类型变量:ClassName other = (ClassName)otherObject

    6. 现在开始对所有需要比较的域进行比较了。使用==比较基本类型域,使用equals比较对象域。如果所有的域都匹配,就返回true;否则返回false。

    如果在子类中重新定义equals,就要在其中包含调用super.equals(other)

    5.2.3 hashCode方法

    散列码(hash code)是由对象导出的一个整形值。散列码是没有规律的。如果x和y是两个不同的对象,x.hashCode()y.hashCode()基本上不会相同。

    由于hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址。

    最好使用null安全的访法Objects.hashCode。如果其参数为null,这个方法会返回0,否则返回对参数调用hashCode的结果。另外,使用静态方法:Double.hashCode可以避免创建Double对象。

    5.2.3 toString方法

    用于返回表示对象值的字符串。toString方法也可以供子类调用。

    5.3 对象包装器与自动装箱

    包装器(wrapper):Integer、Long、Float、Double、Short、Byte、Character、Void和Boolean(前6个派生于公共的超类Number)。对象包装器类是不可变的,一旦构造了包装器,就不允许更改包装在其中的值。同时包装器类还是final,因此不能定义它们的子类。

    ArrayList<Integer> list = new ArrayList<>();
    list.add(3); //  =>  list.add(Integer.valueOf(3))  自动装箱
    
    int n = list.get(i); //  = > int n = list.get(i).intValue();   自动拆箱
    

    image-20200902005901773

    image-20200902005918160

    5.4 枚举类

    先看一个例子:

    public enum Size {
        SMAL,MEDIUM,LARGE,EXTRA_LARGE;
    }
    

    这个声明定义的类型是一个类,有四个实例。

    所有的枚举类型都是Enum类的子类。它们继承了Enum类的许多方法。包含toString,它能够返回枚举常量名。例如Size.SMALL.toString()将返回字符串"SMALL"toString的逆方法是静态方法valueOf,例如:Size s = Enum.valueOf(Size.class,"SMALL");

    每个枚举类型都有一个静态的values方法,它将返回一个包含全部枚举值的数组。

    image-20200902005828729

    5.5 反射

    能够分析类能力的程序称为反射。反射功能及其强大:

    • 在运行时分析类的能力
    • 在运行时查看对象
    • 实现通用的数组操作代码
    • 利用Method对象。

    5.5.1 Class类

    Object类中的getClass()方法将会返回一个Class类型的实例。Class用于保存类的信息。

    可以调用静态方法forName获得类名对应的Class对象。

    5.5.2

    5.6 继承的设计技巧

    1. 将公共操作和域放在超类
    2. 不要使用受保护的域
    3. 使用继承实现“is-a”关系
    4. 除非所有继承的访法都有意义,否则不要使用继承
    5. 在覆盖方法时,不要改变预期的行为
    6. 使用多态,而非类型信息
    7. 不要过多的使用反射
    都说酒是陈的香。
  • 相关阅读:
    解决Cannot download "https://github.com/sass/node-sass/releases/download/binding.nod的问题
    wid是一个字符串 必须转化成整型
    如何获取内联样式的width值
    onresize方法
    jquery中$("#afui").get(0)为什么要加get(0)呢?
    jquery $(document).ready() 与window.onload的区别
    鼠标点击
    添加二级菜单颜色
    homepage左边的导航菜单怎么做的?
    center
  • 原文地址:https://www.cnblogs.com/yihangjou/p/13599648.html
Copyright © 2011-2022 走看看