Java 面向对象编程–继承
一、继承的概念及如何使用
继承(Inheritance)是面向对象的三大特性之一,继承可以解决编程中代码冗余的问题,是实现代码重用的重要手段之一。
继承是软件可重用性的一种表现,使子类具有和父类相同的特征和行为,从而缩短开发周期。此时新类被称为子类,现有的类被称为父类。
Java 语言通过 extends 关键字实现类之间的继承关系。继承最基本的作用就是使代码可重用,增加软件的可扩展性。
继承的理解:
继承表达的是“xx is a xx”的关系,如Dog is a Pet。同样,
可以让 "教师 " 继承 “人”,
让 “西瓜” 继承 “水果”,
让 “小轿车” 继承 “车” 等。
继承通过[访问修饰符] class <SubClass> extends <SuperClass> {}
来实现,其中,SubClass 被称为子类或派生类,SuperClass 被称为父类或基类。
在 Java 中,继承的规则如下:
- 可以继承父类中 public 和 protected 修饰的属性和方法,不论子类和父类是否在同一个包中。
- 可以继承默认访问修饰符修饰的属性和方法,但是子类和父类必须在同一个包中。
- 无法继承 private 修饰的属性和方法。
- 无法继承父类的构造方法。
图解:
注意:在 Java 中只支持单继承,即每个类只能有一个直接父类。
二、Object类
事实上,所有的 Java 类都直接或间接地继承 Object类,它位于java.lang包中。Object类是所有 Java类的“祖先”。在定义一个类时,没有使用extends 关键字,也就是没有显式地继承某个类,那么这个类直接继承 Object 类。所有对象都继承 Object 类的方法。
Object 类定义了大量的可被其他类继承的方法,Object类的常用方法:
方法 | 说明 |
---|---|
toString() | 返回当前对象本身的有关信息,返回字符串对象 |
boolean equals() | 比较两个对象是否是同一个对象,若是,则返回true |
Object clone() | 生成当前对象的一个副本,并返回 |
int hashCode() | 返回该对象的哈希代码值 |
getClass() | 获取当前对象所属的类信息,返回 Cass 对象,即运行时类 |
三、继承关系中的方法重写
定义:
子类通过继承可以拥有和父类相同的特征和行为,另外,子类也可以根据需要,定义自己特有的行为,既沿袭了父类的方法名称,又重新实现了父类方法,这就是方法重写。
在子类中可以根据需求对从父类继承的方法进行重新编写,这被称为方法重写或方法覆盖。
方法重写必须遵守以下规则:
- 重写方法和被重写方法必须具有相同的方法名。
- 重写方法和被重写方法必须具有相同的参数列表。
- 上重写方法的返回值类型必须和被重写方法的返回值类型相同或是其子类。
- 重写方法不能缩小被重写方法的访问权限。
另外,IntelliJ IDEA 工具提供了便捷的方式来实现对父类方法的重写操作。
操作方法:
- 打开你的 Java 项目,并定位到你想要重写父类方法的类文件。
将光标放在你想要重写的方法上(这通常是一个在该类的父类或接口中定义的方法)。 - 使用快捷键 Ctrl + O (Windows/Linux) 或 Cmd + O (Mac) 来打开 “Override Methods” 对话框。
在弹出的对话框中,你将看到可重写的方法列表。选择你想要重写的方法并确认选择。 - IntelliJ IDEA 会自动生成一个新的方法定义,并将其插入到你的类中。你可以在这个方法中添加你的自定义实现。
使用自动生成的代码会在上面出现 “@Override” 的内容,这个是Java注解又被称为 Java 标注,是 Java5 引入的一种注释机制,表示该方法重写了父类的方法,可以写也可以不写,在功能实现上没有区别,但是通过 “@Override” 注解,程序更加方便阅读。另外,编译器也会帮助验证 “@Override” 下面的方法名是否是父类所有的。如果其不符合方法重写规则,则会报错。
方法重载和方法重写的区别是什么?
- 方法重载涉及同一个类中的同名方法,要求方法名相同,参数列表不同,与返回值类型和访问修饰符无关。
- 方法重写涉及的是子类和父类之间的同名方法,要求方法名相同、参数列表相同、返回值类型相同或是其子类。
四、super关键字
super 关键字代表对当前对象的直接父类对象的默认引用。在子类中可以通过 super 关键字访问父类的成员,包括父类的属性和方法。具体语法如下:
访问父类构造方法:super(参数)
访问父类属性或方法:super.<父类属性或方法>
在使用 super 关键字时,需要注意以下几点:
- super关键字必须出现在子类(子类的方法和构造方法)中,而不允许在其他位置。
- 可以访问父类的成员,如父类的属性、方法、构造方法。
- 注意访问权限的限制,如无法通过super关键字访问 private 成员。
例如,在AppleTree 类中可以通过如下语句访问父类成员。其中,父类成员变量为private 且提供getter()方法,成员方法和构造方法都是public。
super("苹果树”,10,2,100);//直接访问父类的构造方法,该语句只能出现在构造方法中
super.getName();//通过 getter()方法访问直接父类的 name 属性
super.print();//直接访问父类的print()方法
注意:
- 在构造方法中如果有 this 语句或super语句,则只能是第一条语句。
- 在一个构造方法中,不允许同时使用tis关键字和 super 关键字调用构造方法(否则就有两条第一条语句)。
- 在静态方法中不允许出现this 关键字或 super 关键字。
- 在实例方法中,this语句和 super语句不要求是第一条语句,可以共存。
五、继承关系中的构造方法
在 Java 中,一个类的构造方法在如下两种情况下总会被执行。
- 创建该类的对象(实例化)。
- 创建该类的子类的对象(子类的实例化)。
因此,子类在实例化时,会首先执行其父类的构造方法,然后才会执行子类的构造方法。换言之,在 Java 语言中,当创建一个对象时,Java 虚拟机会按照父类到子类的顺序执行一系列的构造方法。子类继承父类时构造方法的调用规则如下:
- 如果在类的构造方法中没有通过 super 关键字显式调用父类的带参构造方法,也没有通过 this关键字显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,是否写“super();”语句,效果是一样的。
- 如果在子类的构造方法中通过 super 关键字显式地调用了父类的带参构造方法,那么将执行父类相应的构造方法,而不执行父类无参构造方法。
- 如果在子类的构造方法中通过 this 关键字显式地调用了自身的其他构造方法,那么在相应构造方法中遵循以上两条规则。
- 如果存在多级继承关系,则在创建一个子类对象时,以上规则会多次向更高一级父类应用,直到执行顶级父类 Object类的无参构造方法为止。