【Java SE语法篇】9.抽象类和接口

简介: 【Java SE语法篇】9.抽象类和接口


1. 抽象类

1.1 抽象类的概念

在面向对象的概念中,所有的对象都是通过类来描绘的,但是放过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

1.2 抽象类的语法

在Java 中,一个类如果被abstract 修饰的类成为抽象类,抽象类中被abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。

抽象类的定义格式如下:

abstract class 抽象类名{
    属性;
    
    // 普通方法
    访问权限 返回值类型 方法名称(参数){
        return [返回值];
    }
    
    // 抽象方法,无方法体
    访问权限 abstract 返回值类型 抽象方法名称(参数);
}

从以上格式可以看出,抽象类的定义比普通类多了抽象方法,类的其他功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样

1.3 抽象类的特性

  1. 抽象类不能直接实例化对象

  2. 抽象方法不能是被 private 修饰的

  3. 抽象方法不能被finalstatic修饰,因为抽象方法要被子类重写

  4. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰,如果一个非抽象类继承了抽象类,那么这个子类必须实现抽象类中的全部抽象方法。
abstract class Shape {
    // 抽象方法
    public abstract  void draw();
}
abstract class A extends Shape {
    public abstract void testA();
}
class B extends A {
    @Override
    public void testA() {
    }
    @Override
    public void draw() {
    }
}
  1. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
  2. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

2. 接口

接口用来描述类应该做什么,而不指定它们具体应该如何做。一个类可以实现一个或多个接口。有些情况可能要求符合这些接口,主要有这种要求,就可以使用实现了这个接口的类(即实现类)的对象。

2.1 接口的概念

在Java程序设计语言中,接口不是类,而是对希望符合这个接口的类的一组需求。

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用

在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型

2.2 接口的语法规则

接口的定义格式与定义类的格式基本相同,将class 关键字换成interface关键字,就定义了一个接口。

public interface 接口名称{
    // 抽象方法
}

注意事项:

  1. 创建接口时,接口的命名一般以大写字母I开头
  2. 接口命名一般使用“形容词”词性的单词。

2.3 接口的使用

接口不能直接被使用,必须有一个"实现类"来实现该接口,实现接口的所有的抽象方法。

public class 类名 interface 接口名称{ // 可以使用,分隔,实现多个接口
    // ...
}

注意:子类和父类之间是extends 继承关系,类与接口之间是implements 实现关系。

2.4 接口的特性

  1. 接口类型是一种引用类型,但是不能直接new 接口的对象

  2. 接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public abstract(只能是
    public abstract,其他修饰符都会报错)

  3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现

  4. 重写接口中方法时,不能使用默认的访问权限

  5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量

  1. 接口中不能有静态代码块和构造方法(编译错误)

  2. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
  3. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类

2.5 实现多个接口

在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承但是一个类可以实现多个接口。下面通过类来表示一组动物。

abstract public class Animal {
    public String name;
    public Animal(String name) {
        this.name = name;
    }
}

另外我们再提供一组接口, 分别表示 “会飞的”, “会跑的”, “会游泳的”。

interface IFly {
    void fly();
}
interface IRun {
    void run();
}
interface ISwim {
    void swim();
}

接下来我们创建几个具体的动物:

猫, 是会跑的。

public class Cat extends Animal implements IRun{
    public Cat(String name) {
        super(name);
    }
    @Override
    public void run() {
        System.out.println(this.name + "正在用四条腿跑");
    }
}

鱼,是会游泳的

public class Fish extends Animal implements ISwim{
    public Fish(String name) {
        super(name);
    }
    
    @Override
    public void swim() {
        System.out.println(this.name + "正在游泳");
    }
}

青蛙,既能跑,又能游泳(两栖动物)

public class Fish extends Animal implements IRun,ISwim{
    public Fish(String name) {
        super(name);
    }
    
    @Override
    public void run() {
        System.out.println(this.name + "正在用两条腿跑");
    }
    
    @Override
    public void swim() {
        System.out.println(this.name + "正在游泳");
    }
}

注意:一个类实现多个接口,每个接口的抽象方法都要实现,否则类必须设置为抽象类

而鸭子即可以飞,又能跑、还可以游泳。

public class Duck extends Animal implements IFly,IRun,ISwim{
    public Duck(String name) {
        super(name);
    }
    @Override
    public void fly() {
        System.out.println(this.name + "正在用两个翅膀飞");
    }
    @Override
    public void run() {
        System.out.println(this.name + "正在用两条腿跑");
    }
    @Override
    public void swim() {
        System.out.println(this.name + "正在用两条腿游泳");
    }
}

上面的代码展示了 Java 面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口

继承表达的含义是 is-a 语义, 而接口表达的含义是 具有 xxx 特性 .

猫是一种动物,具有跑的特性。

鱼是一种动物,具有游泳的特性。

青蛙是一种,具有跑和游泳的特性。

鸭子是一种动物,具有跑、游泳和飞的特性。

这样设计有什么好处呢? 时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型,而只关注某个类是否具备某种能力.

例如:现在定义一个方法:testRun

public static void testRun(IRun iRun) {
    iRun.run();
}

在这个testRun方法内部, 我们并不关注到底是哪种动物, 只要参数是会跑的, 就行。

public static void main(String[] args) {
    testRun(new Bird("布谷"));
    testRun(new Duck("唐老鸭"));
    testRun(new Dog("旺财"));
}
// 运行结果
布谷正在用两条腿跑
唐老鸭正在用两条腿跑
旺财正在用四条腿跑

甚至参数可以不是 “动物”, 只要会跑!

class Roboot implements IRun{
    @Override
    public void run() {
        System.out.println("机器人正在用两条腿跑");
    }   
}
public class Test {
    public static void testRun(IRun iRun) {
    iRun.run();
  }
    
    public static void main(String[] args) {
        testRun(new Roboot());
    }
}
// 运行结果
机器人正在用两条腿跑

2.6 接口之间的继承

在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的

接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字.

interface IRun {
    void run();
}
interface ISwim {
    void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRun,ISwim{
    
}
public class Frog extends Animal implements IAmphibious{
    ...
}

通过接口继承创建一个新的接口IAmphibious 表示 “两栖的”. 此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法.

接口间的继承相当于把多个接口合并在一起.

3. 抽象类和接口的区别

抽象类和接口都是 Java 中多态的常见使用方式. 都需要重点掌握. 同时又要认清两者的区别。

核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法。

如之前写的 Animal 例子. 此处的 Animal 中包含一个 name 这样的属性, 这个属性在任何子类中都是存在的. 因此此处的 Animal 只能作为一个抽象类, 而不应该成为一个接口.

public class Animal {
    public String name;
    public Animal(String name) {
        this.name = name;
    }
}
区别 抽象类 接口
结构组成: 普通类 + 抽象方法 抽象方法 + 静态常量
权限: 各种权限 public
子类使用: 使用extends关键字继承抽象类 使用implements 关键字实现接口
关系: 一个抽象类可以实现若干接口 接口不能继承抽象类,但是接口可以使用extends 关键字继承多个父接口
子类权限: 一个子类只能继承一个抽象类 一个子类可以实现多个接口
相关文章
|
8天前
|
Java
Java基础语法与面向对象
重载(Overload)指同一类中方法名相同、参数列表不同,与返回值无关;重写(Override)指子类重新实现父类方法,方法名和参数列表必须相同,返回类型兼容。重载发生在同类,重写发生在继承关系中。
55 1
|
18天前
|
存储 SQL NoSQL
Redis-常用语法以及java互联实践案例
本文详细介绍了Redis的数据结构、常用命令及其Java客户端的使用,涵盖String、Hash、List、Set、SortedSet等数据类型及操作,同时提供了Jedis和Spring Boot Data Redis的实战示例,帮助开发者快速掌握Redis在实际项目中的应用。
174 1
Redis-常用语法以及java互联实践案例
|
19天前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
85 1
|
2月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
162 23
|
2月前
|
存储 安全 Java
Java集合框架(一):List接口及其实现类剖析
本文深入解析Java中List集合的实现原理,涵盖ArrayList的动态数组机制、LinkedList的链表结构、Vector与Stack的线程安全性及其不推荐使用的原因,对比了不同实现的性能与适用场景,帮助开发者根据实际需求选择合适的List实现。
|
2月前
|
数据采集 JSON Java
Java爬虫获取1688店铺所有商品接口数据实战指南
本文介绍如何使用Java爬虫技术高效获取1688店铺商品信息,涵盖环境搭建、API调用、签名生成及数据抓取全流程,并附完整代码示例,助力市场分析与选品决策。
|
2月前
|
算法 Java 测试技术
零基础学 Java: 从语法入门到企业级项目实战的详细学习路线解析
本文为零基础学习者提供完整的Java学习路线,涵盖语法基础、面向对象编程、数据结构与算法、多线程、JVM原理、Spring框架、Spring Boot及项目实战,助你从入门到进阶,系统掌握Java编程技能,提升实战开发能力。
122 0
|
2月前
|
存储 Java 容器
Java基本语法详解
本文深入讲解了Java编程的基础语法,涵盖数据类型、运算符、控制结构及数组等核心内容,帮助初学者构建坚实的编程基础。
|
2月前
|
安全 Java 开发者
Java集合框架:详解Deque接口的栈操作方法全集
理解和掌握这些方法对于实现像浏览器后退功能这样的栈操作来说至关重要,它们能够帮助开发者编写既高效又稳定的应用程序。此外,在多线程环境中想保证线程安全,可以考虑使用ConcurrentLinkedDeque,它是Deque的线程安全版本,尽管它并未直接实现栈操作的方法,但是Deque的接口方法可以相对应地使用。
126 12
|
存储 安全 Java
Java8语法最佳实践-什么是对象(下)
计算机革命起源机器。编程语言就像是那台机器。它不仅是我们思维放大的工具与另一种表达媒介,更像是我们思想的一部分。语言的灵感来自其他形式的表达,如写作,绘画,雕塑,动画和电影制作。编程语言就是创建应用程序的思想结构。
133 0