实现继承,包括可见性修饰符和组合。从 Object 类中重写 hashCode、 equals 和 toString 方法。实现多态性。开发使用抽象类和方法的代码。

继承

继承是指一个 IS-A 关系,其中一个类(称为超类)为派生的或更专门的类(称为子类)提供了公共属性和方法。
在 Java 中,一个类只允许从一个超类继承(单数继承)。当然,惟一的例外是 java.lang.Object,Object没有父类类。这个类是所有类的超类。
当子类定义在与超类不同的包中时,只有私有private和具有默认可见性的成员是不被继承的。虽然不能被继承,但如果父类的公共方法使用到了父类的私有字段,该方法也是可以被继承的,只是子类无法使用父类的私有字段。如果没有修饰符则为默认修饰符则在同一个包下可以被继承,其他与上述一样
this和super关键字无法指向静态变量,只能使用类Class或者实例变量指向静态变量。
继承的属性或方法具有与超类中定义的属性或方法相同的可见性级别。但是,对于方法,你可以更改它们以使其更加可见,但是你不能使它们更加不可见:

class Tool {
    public int size;
    public int getSize() { return size; }
}

class Hammer extends Tool {
    private int size; // No problem!
    // Compile-time error
    private int getSize() { return size; }
}

关于子类

  • 继承的属性可以像其他属性一样直接使用
  • 可以在子类中用与超类中的属性相同的名称声明属性,从而隐藏它
  • 不在超类中的新属性可以在子类中声明
  • 可以按原样直接使用继承的方法
  • 可以在具有与超类中的签名相同的子类中声明一个新的实例方法,从而重写它
  • 一个新的static方法可以在具有与超类中的签名相同的子类中声明,从而隐藏它
  • 不在超类中的新方法可以在子类中声明
  • 可以在调用超类的构造函数的子类中声明构造函数,可以隐式地,也可以通过使用关键字super来声明

对于方法,不允许降低它们的可见性,因为它们以不同的方式处理,换句话说,方法要么被重写,要么被重载。

重载和重写

重载和重写之间的区别与方法签名有很大关系
方法签名是方法的名称及其参数列表(包括参数的类型和数量)。请注意,此定义中不包括返回类型。

重载

当调用重载方法时,编译器必须决定调用该方法的哪个版本。第一个显而易见的候选方法是调用与参数的数量和类型完全匹配的方法。但是如果没有一个完全匹配会怎么样呢?
要记住的规则是,Java 将首先查找最接近的匹配(这意味着更大的类型、超类、自动装箱类型或更特殊的类型)。

class Print {
    static void printType(short param) {
        System.out.println("short");
    }
    static void printType(long param) {
        System.out.println("long");
    }
    static void printType(Integer param) {
        System.out.println("Integer");
    }
    static void printType(CharSequence param) {
       System.out.println("CharSequence");
    }

    public static void main(String[] args) {
        byte b = 1;
        int i = 1;
        Integer integer = 1;
        String s = "1";

        printType(b);
        printType(i);
        printType(integer);
        printType(s);
   }
}

输出结果为
image.png
原因

  • 在第一个方法调用中,参数类型为 byte。没有获取字节的方法,因此最接近的较大类型为 short。
  • 在第二个方法调用中,参数类型是 int。没有接受 int 类型的方法,因此最接近的较大类型是 long 类型(注意,这个类型的优先级高于 Integer 类型)。
  • 在最后一个方法调用中,参数类型是 String。没有接受 String 的方法,因此最接近的超类是 CharSequence。image.png

如果它找不到匹配项,或者编译器因为调用不明确而无法决定,则会引发编译错误。例如,考虑到前面的类,下面的代码会导致一个错误,因为没有比 double 更大的类型,而且它不能被自动装箱为 Integer:
image.png

下面是一个模糊调用的例子,也会报错:
image.png

重写

如果在子类中定义了与超类中的静态static方法具有相同签名的静态方法,则该方法是 HIDDEN,而不是 overrited。

  • 返回类型必须是相同的或者是子类型
  • 抛出子句中的异常必须是这些异常的相同、更少或子类

Object类方法

image.png
此类具有以下可重写(重定义)的方法:

  • protected Object clone() throws CloneNotSupportedException
  • protected void finalize() throws Throwable
  • public int hashCode()
  • public boolean equals(Object obj)
  • public String toString()

最重要的方法是 hashCode、 equals 和 toString,自定义类几乎都需要重写

public int hashCode()

它返回对象的哈希代码值。返回的值必须具有以下约定:

  • 每当在 Java 应用程序执行期间对同一对象多次调用时,hashCode方法必须始终返回相同的整数,前提是不修改对象上的 equals 比较中使用的任何信息。从应用程序的一次执行到同一应用程序的另一次执行,这个hashcode整数不需要保持一致
  • 如果两个对象根据equals(Object)判定为true,则hashCode方法必须产生相同的整数结果
  • 如果根据equals(方法)两个对象不相等,则对两个对象中hashCode方法值也可能相同(不必要条件)。但是,为不相等的对象生成不同的整数结果可能会提高hash tables.java.lang.Object(hashCode)的性能

public boolean equals(Object obj)

另一个对象是否等于调用该方法的对象。每当重写此方法时,都需要重写 hashCode 方法,因为 hashCode 方法的契约规定相等的对象必须具有相等的哈希代码。

equals遵循规则

  • 反身性 x.equals(x) true
  • 若y.equals(x) true 则 x.equals(y) true
  • 传递性 若x.equals(y) true 且 y.equals(z) true 则 x.equals(z) true
  • 多次调用一致性

public String toString()

它返回对象的字符串表示形式。用于类 Object 的 toString 方法返回一个字符串,该字符串包含对象作为实例的类的名称、符号字符“@”和对象的哈希代码的无符号十六进制表示形式。

重写规则

遵循重写的一般性规则

  • 访问修饰符必须是相同的或更易访问的
  • 返回类型必须是相同的或子类
  • 名字必须相同(方法签名)
  • 参数列表类型必须相同
  • 抛出相同的异常或其子类

多态

对象根据其类型改变其行为的能力。
重写也称为动态多态性,因为对象的类型是在运行时决定的。
重载也称为静态多态性,因为它是在编译时解决的。

抽象类Abstract和方法

抽象类不能被实例化,只能被继承。它们用 Abstract 关键字声明

  • Abstract 关键字只能应用于类或非静态方法。
  • 如果抽象类的子类没有为所有抽象方法提供实现,那么子类也必须被声明为抽象类。

这个家伙很懒,啥也没有留下😋