【Java开发指南 | 第二十四篇】Java继承

简介: 【Java开发指南 | 第二十四篇】Java继承

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
  }
}


目录
相关文章
|
24天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
|
24天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
33 2
|
24天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
28 2
|
24天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
28 1
|
1月前
|
Java 测试技术 编译器
Java零基础-继承详解!
【10月更文挑战第4天】Java零基础教学篇,手把手实践教学!
34 2
|
1月前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
21 5
|
1月前
|
Java
java继承和多态详解
java继承和多态详解
42 5
|
1月前
|
Java 编译器
【一步一步了解Java系列】:子类继承以及代码块的初始化
【一步一步了解Java系列】:子类继承以及代码块的初始化
24 3
|
1月前
|
Java 测试技术 编译器
Java零基础-继承详解!
【10月更文挑战第6天】Java零基础教学篇,手把手实践教学!
22 0
|
1月前
|
Java 程序员 编译器
【Java】继承、super、final、子类构造方法
【Java】继承、super、final、子类构造方法
26 0