目录
概念
继承是面向对象编程中的重要概念之一,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以重写父类的方法,并且根据需要添加新的属性和方法。这样可以实现代码的复用和扩展,提高代码的可维护性和可扩展性。
Java中实现继承的关键字是extends,子类使用extends关键字后面跟着父类名称来声明继承关系。子类可以继承父类的非私有属性和方法,并且可以添加新的属性和方法。子类也可以覆盖(重写)从父类继承的方法,以实现自己特定的行为。
类的继承格式
class 父类 {
}
class 子类 extends 父类 {
}
接下来通过一个案例学习子类是如何继承父类。
// 父类
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + "正在吃东西");
}
}
// 子类
class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类的构造方法
}
// 重写父类的方法
@Override
public void eat() {
System.out.println(name + "正在啃骨头");
}
// 子类新增的方法
public void bark() {
System.out.println(name + "在汪汪叫");
}
}
public class InheritanceExample {
public static void main(String[] args) {
Dog dog = new Dog("旺财");
dog.eat(); // 调用子类的eat方法
dog.bark(); // 调用子类新增的bark方法
}
}
在继承中,需要注意以下详细问题:
- 单继承:Java中一个类只能有一个直接父类。这是为了避免多重继承可能带来的复杂性和潜在的冲突。例如,一个类不能同时继承类A和类B,但可以继承其中一个类。
- 多个类继承同一父类:多个类可以继承同一个父类。这种情况下,子类会继承父类的属性和方法,实现代码的重用。例如,类B和类C都可以继承类A,从而获得类A的成员变量和方法。
- 多层继承:一个类的父类可以再继承其他父类,形成多层继承关系。这时,该类就成为多个父类的子类,并且会继承所有祖先类的成员变量和方法。例如,类C继承自类B,而类B继承自类A,那么类C即是类A的子类,也是类B的子类。
- 子类与父类的关系:子类是相对于父类而言的。一个类可以是另一个类的子类,同时也可以是其他类的父类。例如,在多层继承中,类B是类A的子类,同时也是类C的父类。
- 访问权限:子类可以访问父类的公有和受保护成员(方法和属性),但不能直接访问父类的私有成员。私有成员只能在定义该成员的类中访问。子类可以通过继承父类的非私有方法来间接调用父类的私有成员。
继承的特性包括:
- 子类拥有父类非私有的属性和方法:子类可以继承父类的公有和受保护成员,即可以访问和使用父类中被继承的非私有属性和方法,从而实现代码的重用。
- 子类可以对父类进行扩展:子类可以添加自己的属性和方法,从而对父类进行功能扩展。这允许在继承基础上更灵活地定制和增强类的行为。
- 子类可以实现父类的方法:子类可以根据自身的需要重新实现(覆盖)父类中的方法,从而给予该方法新的实现逻辑。这称为方法重写(override),它允许子类根据自己的需求对继承自父类的方法进行个性化定制。
- 单继承和多重继承:Java的继承是单继承的,一个类只能继承一个直接父类。但是,通过多层继承,可以实现多个类之间的继承关系,形成继承链。例如,类C继承自类B,而类B继承自类A,类C既是类A的子类,也是类B的子类。
继承的确提高了类之间的耦合性,但过度的耦合性可能导致代码之间的关联过于紧密,降低了代码的独立性和可维护性。因此,在使用继承时需要谨慎设计,遵循合理的继承关系,同时考虑其他代码组织技巧来降低耦合性,如接口、组合等。
继承关键字
super关键字
当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,Java提供了super关键字,super关键字是Java中的一个特殊关键字,用于在子类中访问父类的成员变量、方法和构造函数。它可以在子类中引用父类的成员,以便在子类中进行操作或调用。
在使用super关键字时,有以下几种情况:
- 访问父类的成员变量:通过super.成员变量名的方式访问父类的成员变量。
- 调用父类的方法:通过super.方法名(参数列表)的方式调用父类的方法。
- 在子类构造函数中调用父类的构造函数:通过super(参数列表)的方式调用父类的构造函数。这种情况通常发生在子类需要对继承自父类的属性进行初始化时。
注意:
- super关键字只能在子类中使用,用于与父类进行交互。在访问父类的成员或调用父类的方法时,可以使用super关键字标识明确指向父类。
- 通过super()调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次。
以下是关于super
关键字的示例
class Parent {
protected int num; // 父类的成员变量
public Parent(int num) { // 父类的构造方法
this.num = num;
}
public void display() { // 父类的成员方法
System.out.println("Parent: " + num);
}
}
class Child extends Parent {
private String name; // 子类的成员变量
public Child(int num, String name) { // 子类的构造方法
super(num); // 使用super关键字调用父类的构造方法
this.name = name;
}
public void display() { // 子类的成员方法
super.display(); // 使用super关键字调用父类的成员方法
System.out.println("Child: " + name);
}
}
public class myclass {
public static void main(String[] args) {
Child child = new Child(20, "Tom");
child.display();
}
}
输出结果为:
Parent: 20
Child: Tom
super与this关键字的作用非常相似,都可以调用构造方法、普通方法和属性,但是两者之间还是有区别的,super与this的区别如下表。
区别点 | this | super |
属性访问 | 访问本类中的属性,如果本类中没有该属性,则从父类中查找。 | 访问父类中的属性 |
方法 | 访问本类中的方法,如果本类中没有该方法,则从父类中继续查找 | 直接访问父类中的方法 |
调用构造 | 调用本类构造,必须放在构造方法的首行 | 调用父类构造,必须放在子类构造方法的首行 |
注意:this和super两者不可以同时出现,因为this和super在调用构造方法时都要求必须放在构造方法的首行。
final关键字
final的英文意思是“最终”。在Java中,可以使用final关键字声明类、属性、方法,在声明时需要注意以下几点:
(1)使用final修饰的类不能有子类(不能被继承)。
(2)使用final修饰的方法不能被子类重写。
(3)使用final修饰的变量(成员变量和局部变量)是常量,常量不可修改。
以下是关于final关键字的示例
// 使用final关键字修饰的类
final class FinalClass {
// 使用final关键字修饰的静态属性
public static String Final = "这是final静态字符串。";
// 使用final关键字修饰的成员方法
public final void finalMethod() {
System.out.println("这是final方法。");
}
}
/*class Final1 extends FinalClass{
错误!无法继承 final 类
}*/
public class myclass {
public static void main(String[] args) {
// 创建FinalClass的实例
FinalClass finalClass = new FinalClass();
// 调用finalMethod
finalClass.finalMethod();
// 修改final_string的值,将会抛出异常
FinalClass.Final= "这是不允许的修改。";
// 调用使用final关键字修饰的静态属性,将会抛出异常
System.out.println(FinalClass.Final);
}
}
输出结果为:
这是final方法。
这是不允许的修改。