Java继承
当两个Java文件存在大量重复的内容时,代码会显得冗长、臃肿,且维护起来不够高效。为了解决这个问题,可以考虑通过继承的方式,将这些重复的部分提取出来,组成一个父类。
首先,我们可以创建一个父类,其中包含两个Java文件中共享的方法或属性。然后,让这两个Java文件分别继承这个父类。这样一来,就可以避免代码的重复,并且提高了代码的可维护性和可扩展性。
类的继承格式
class 父类 {
}
class 子类 extends 父类 {
}
继承类型
需要注意的是 Java 不支持多继承,但支持多重继承。
继承的特性
1、子类拥有父类非私有的属性和方法: 子类可以访问并继承父类中非私有的属性和方法,这使得代码的复用性更高。
2、子类可以拥有自己的属性和方法: 子类可以在继承父类的基础上添加新的属性和方法,从而实现对父类的扩展。
3、子类可以重写父类的方法: 子类可以对父类中的方法进行重写(覆盖),以实现自己的功能需求。这种多态性的特性提供了灵活性和可定制性。
4、Java的单继承和多重继承: Java只支持单继承,即一个子类只能继承一个父类。但通过接口可以实现多重继承的效果,因为一个类可以实现多个接口。
5、提高了类之间的耦合性: 继承确实会增加类之间的耦合性,因为子类与父类之间存在依赖关系。高耦合度可能导致代码的独立性降低,但适当的继承设计可以降低耦合度,例如通过合理的抽象和接口设计来实现松耦合。
如何继承
在Java中,要实现继承,需要使用关键字
extends关键字
我们常用extends关键字实现继承。在Java中,类的继承是单一继承,也就是说,一个子类只能继承一个父类,因此使用extends关键字只能继承一个类。
示例如下:
class Animal { void makeSound() { System.out.println("It makes a sound."); } } class Dog extends Animal{ } public class Ice{ public static void main(String[] args) { Dog dog=new Dog(); dog.makeSound(); } }
implements关键字
在Java中,使用implements关键字可以实现类与接口之间的关系,这样类就可以间接具有多重继承的特性。
当一个类实现了某个接口时,它必须实现该接口中声明的所有方法。
一个类可以实现多个接口,接口之间用逗号分隔。
// 定义一个接口A interface A { void methodA(); } // 定义另一个接口B interface B { void methodB(); } // 定义一个类,实现接口A和接口B class III implements A, B { // 实现接口A中的方法 public void methodA() { System.out.println("Method A implementation"); } // 实现接口B中的方法 public void methodB() { System.out.println("Method B implementation"); } } // 测试类 public class Ice { public static void main(String[] args) { // 创建III对象 III ice = new III(); // 调用实现的方法 ice.methodA(); ice.methodB(); } }
super 与 this 关键字
super关键字: 在子类中,可以使用super关键字来引用父类的成员(方法、字段),以便在子类中重写父类的方法或访问父类的构造方法。
this关键字: 在Java中,this关键字表示对当前对象的引用。它可以用于访问当前对象的字段、方法或者调用当前类的构造方法。
class Animal { void eat() { System.out.println("animal : eat"); } } class Dog extends Animal { void eat() { System.out.println("dog : eat"); } void eatTest() { this.eat(); // 使用this调用Dog类的eat方法 super.eat(); // 使用super调用Animal类的eat方法 } } public class Ice { public static void main(String[] args) { Animal a = new Animal(); a.eat(); // 输出 "animal : eat" Dog d = new Dog(); d.eatTest(); // 输出 "dog : eat" 和 "animal : eat" } }
final 关键字
final 关键字可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
当 final 关键字用于类时,它将该类定义为最终类,意味着它不能被继承。同样地,当 final 用于方法时,它将该方法定义为最终方法,不能被子类重写。
声明类:
final class 类名 { //类体 }
声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){ //方法体 }
注: final 定义的类,其中的属性、方法不是 final 的。
示例,Cat 类继承自 Dog 类,但是 Dog 类被声明为 final,意味着它不能被继承。这会导致编译错误:
class Animal { void eat() { System.out.println("animal : eat"); } } final class Dog extends Animal { void eat() { System.out.println("dog : eat"); } } class Cat extends Dog{ void eat() { System.out.println("cat : eat"); } } public class Ice { public static void main(String[] args) { Animal a = new Animal(); a.eat(); // 输出 "animal : eat" Dog d = new Dog(); d.eat(); // 输出 "dog : eat" Cat c = new Cat(); c.eat(); } }
构造器
继承中常用的是构造器。
在继承时,子类不继承父类的构造器(构造方法或者构造函数),而是通过调用(隐式或显式)来使用它们。
1、如果父类的构造器带有参数,则必须在子类的构造器中显式地使用 super 关键字调用父类的构造器,并传递适当的参数列表。
2、如果父类的构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类的构造器,系统会自动调用父类的无参构造器。
class superclass{ private int n; superclass(){ System.out.println("1"); } superclass(int n){ System.out.println(n); } } //继承 class super1 extends superclass{ private int n; super1(){// 自动调用父类的无参数构造器,输出1 System.out.println("2");//输出2 } public super1(int n) { super(n);// 显式调用父类的有参数构造器 } } public class Ice{ public static void main(String args[]) { super1 iii = new super1(); super1 ccc = new super1(100);//显式调用了父类的有参数构造函数 super(n),输出100 } }