Java入门系列-18-抽象类和接口

简介:

抽象类

在第16节继承中,有父类 People

People people=new People();
people.sayHi();

实例化People是没有意义的,因为“人”是一个抽象的概念。

怎么才能避免父类的实例化呢?使用 abstract 关键字修饰类(抽象类)。

抽象父类

public abstract class People {
    private String name;
    
    public People(String name) {
        super();
        this.name = name;
    }

    //人类共有方法 哭
    public void cry() {
        System.out.println("呜呜");
    }
    //抽象方法 不做具体实现
    public abstract void sayHi();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

子类:Chinese.java

//中国人
public class Chinese extends People{

    public Chinese(String name) {
        super(name);
    }

    //必须实现
    @Override
    public void sayHi() {
        System.out.println(this.getName()+":你好!");
    }
}

子类:Britisher.java

//英国人
public class Britisher extends People{

    public Britisher(String name) {
        super(name);
    }

    @Override
    public void sayHi() {
        System.out.println(this.getName()+":Hello!");
    }
}

测试类

public class TestPeople {

    public static void main(String[] args) {
        //People people=new People("张三");//去掉注释试试
        People chinese=new Chinese("张三");
        chinese.sayHi();
        People britisher=new Britisher("John");
        britisher.sayHi();
    }
}

被关键字 abstract 修饰的类是抽象类,抽象类不能实例化

被关键字 abstract 修饰的方法是抽象方法,抽象方法没有方法体

抽象方法必须在抽象类里

抽象方法必须在子类中被实现,除非子类是抽象类

抽象方法没有方法体

public abstract void sayHi();

注意:被 abstract 修饰后不能使用 final 修饰!

接口

如何实现防盗门这个类?门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能,将门和锁分别定义为抽象类。但是防盗门可以继承门的同时又继承锁吗?不能,防盗门不是锁,不符合 is a 的关系而且Java只支持单继承。

接口的语法

public interface MyInterface {
    public abstract void foo();
}

接口可以认为是纯粹的抽象类

接口中的方法都是抽象方法 (public abstract)

接口不可以被实例化

实现类必须实现接口中的所有方法

接口中的变量都是静态常量

接口之间可以互相继承(extedns),类只能实现接口(implements)

一个类可以继承一个父类,实现多个接口

演示接口的继承及实现接口

父接口:A.java

public interface A {
    void methodA();
}

子接口:B.java

public interface B extends A{
    void methodB();
}

接口的实现类:C.java

public class C implements B{

    @Override
    public void methodA() {
    }

    @Override
    public void methodB() {
    }
}

接口表示能力

面向接口编程时,关心实现类有何能力,而不关心实现细节。面向接口的约定而不考虑接口的具体实现。

在鸟类中,白鹭可以飞,鸵鸟不能飞,所以在这里飞是一种能力,下面看一下代码的设计。

飞行接口:Fly.java

//表示飞行能力
public interface Fly {
    /**
     * 飞行
     */
    public abstract void fly();
}

游泳接口:Swim.java

//表示游泳能力
public interface Swim {
    public abstract void swim();
}

鸟类:Bird.java

//抽象鸟类 重用代码
public abstract class Bird {
    /**
     * 下蛋
     */
    public void layEggs() {
        System.out.println("产出一枚蛋");
    }
}

白鹭类:Egret.java

//白鹭类
public class Egret extends Bird implements Fly,Swim{

    @Override
    public void fly() {
        System.out.println("使劲煽动翅膀后起飞");
    }

    @Override
    public void swim() {
        System.out.println("漂在了水面上,轻松的游来游去");
    }
}

鸵鸟类:Ostrich.java

//鸵鸟类
public class Ostrich extends Bird implements Swim{

    @Override
    public void swim() {
        System.out.println("漂在了水面了,开始游动");
    }
}

测试类

public class TestBird {
    public static void main(String[] args) {
        Egret egret=new Egret();
        egret.swim();
        egret.fly();
        Ostrich ostrich=new Ostrich();
        ostrich.swim();
    }
}

接口表示约定

在生活中,我们使用的插座,规定了两个接头剪得额定电压、两个接头间的距离、接头的形状。

在代码中约定体现在接口名称和注释上

下面使用面向接口编程实现一台计算机的组装,计算机的组成部分有:CPU、硬盘、内存。

先创建 CPU、硬盘、内存接口

package computer;

/**
 * CPU 接口
 * @author Jack
 *
 */
public interface CPU {
    /**
     * 获取CPU品牌
     * @return
     */
    String getBrand();
    
    /**
     * 获取CPU主频
     * @return
     */
    Float getFrequency();
}
package computer;

/**
 * 硬盘接口
 * @author Jack
 *
 */
public interface HardDisk {
    
    /**
     * 获取硬盘容量
     * @return
     */
    int getCapacity();
}
package computer;

/**
 * 内存接口
 * @author Jack
 *
 */
public interface EMS {
    /**
     * 获取内存容量
     * @return
     */
    int getSize();
}

将接口设计到计算机类中

package computer;
/**
 * 计算机类
 * @author Jack
 *
 */
public class Computer {
    private CPU cpu;//cpu接口
    private HardDisk hardDisk;//硬盘接口
    private EMS ems;//内存接口

    public Computer() {
    }

    public Computer(CPU cpu, HardDisk hardDisk, EMS ems) {
        super();
        this.cpu = cpu;
        this.hardDisk = hardDisk;
        this.ems = ems;
    }

    public CPU getCpu() {
        return cpu;
    }

    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }

    public HardDisk getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }

    public EMS getEms() {
        return ems;
    }

    public void setEms(EMS ems) {
        this.ems = ems;
    }
}

创建 CPU、硬盘、内存接口的实现

package computer.impl;

import computer.CPU;

/**
 * 英特尔 CPU
 * @author Jack
 *
 */
public class IntelCPU implements CPU{

    @Override
    public String getBrand() {
        return "英特尔";
    }

    @Override
    public Float getFrequency() {
        return 2.3f;
    }
}
package computer.impl;

import computer.HardDisk;

/**
 * 闪迪硬盘
 * @author Jack
 *
 */
public class SanDisk implements HardDisk{

    @Override
    public int getCapacity() {
        return 3000;
    }
}
package computer.impl;

import computer.EMS;

/**
 * 金士顿 内存
 * @author Jack
 *
 */
public class JSDEMS implements EMS{

    @Override
    public int getSize() {
        return 4;
    }
}

完成计算机及组件的组装进行测试

package computer;

import computer.impl.IntelCPU;
import computer.impl.JSDEMS;
import computer.impl.SanDisk;

public class TestComputer {
    public static void main(String[] args) {
        CPU cpu=new IntelCPU();//创建CPU
        HardDisk sanDisk=new SanDisk();//创建硬盘
        EMS jsdEMS=new JSDEMS();//创建内存
        Computer computer=new Computer(cpu,sanDisk,jsdEMS);
        System.out.println("CPU型号:"+computer.getCpu().getBrand());
        System.out.println("硬盘容量:"+computer.getHardDisk().getCapacity()+" GB");
        System.out.println("内存容量:"+computer.getEms().getSize()+" GB");
    }
}

接口总结

接口有比抽象类更好的特性:
1.可以被多继承
2.设计和实现完全分离
3.更自然的使用多态
4.更容易搭建程序框架
5.更容易更换实现

搜索关注公众号「享智同行」,第一时间获取技术干货

相关文章
|
1月前
|
安全 Java 数据库连接
2025 年最新 Java 学习路线图含实操指南助你高效入门 Java 编程掌握核心技能
2025年最新Java学习路线图,涵盖基础环境搭建、核心特性(如密封类、虚拟线程)、模块化开发、响应式编程、主流框架(Spring Boot 3、Spring Security 6)、数据库操作(JPA + Hibernate 6)及微服务实战,助你掌握企业级开发技能。
251 3
|
1月前
|
数据采集 JSON Java
Java爬虫获取1688店铺所有商品接口数据实战指南
本文介绍如何使用Java爬虫技术高效获取1688店铺商品信息,涵盖环境搭建、API调用、签名生成及数据抓取全流程,并附完整代码示例,助力市场分析与选品决策。
|
1月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
144 23
|
21天前
|
前端开发 Java 数据库连接
帮助新手快速上手的 JAVA 学习路线最详细版涵盖从入门到进阶的 JAVA 学习路线
本Java学习路线涵盖从基础语法、面向对象、异常处理到高级框架、微服务、JVM调优等内容,适合新手入门到进阶,助力掌握企业级开发技能,快速成为合格Java开发者。
266 3
|
1月前
|
安全 Java 开发者
Java集合框架:详解Deque接口的栈操作方法全集
理解和掌握这些方法对于实现像浏览器后退功能这样的栈操作来说至关重要,它们能够帮助开发者编写既高效又稳定的应用程序。此外,在多线程环境中想保证线程安全,可以考虑使用ConcurrentLinkedDeque,它是Deque的线程安全版本,尽管它并未直接实现栈操作的方法,但是Deque的接口方法可以相对应地使用。
118 12
|
1月前
|
NoSQL Java 关系型数据库
Java 从入门到进阶完整学习路线图规划与实战开发最佳实践指南
本文为Java开发者提供从入门到进阶的完整学习路线图,涵盖基础语法、面向对象、数据结构与算法、并发编程、JVM调优、主流框架(如Spring Boot)、数据库操作(MySQL、Redis)、微服务架构及云原生开发等内容,并结合实战案例与最佳实践,助力高效掌握Java核心技术。
218 1
|
1月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
1月前
|
Java 编译器 API
Java Lambda表达式与函数式编程入门
Lambda表达式是Java 8引入的重要特性,简化了函数式编程的实现方式。它通过简洁的语法替代传统的匿名内部类,使代码更清晰、易读。本文深入讲解Lambda表达式的基本语法、函数式接口、方法引用等核心概念,并结合集合操作、线程处理、事件回调等实战案例,帮助开发者掌握现代Java编程技巧。同时,还解析了面试中高频出现的相关问题,助你深入理解其原理与应用场景。
|
12天前
|
Java API 数据库
2025 年最新 Java 实操学习路线,从入门到高级应用详细指南
2025年Java最新实操学习路线,涵盖从环境搭建到微服务、容器化部署的全流程实战内容,助你掌握Java 21核心特性、Spring Boot 3.2开发、云原生与微服务架构,提升企业级项目开发能力,适合从入门到高级应用的学习需求。
235 0
|
22天前
|
监控 Java API
2025 年全新出炉的 Java 学习路线:从入门起步到实操精通的详细指南
2025年Java学习路线与实操指南,涵盖Java 21核心特性、虚拟线程、Spring Boot 3、微服务、Spring Security、容器化部署等前沿技术,助你从入门到企业级开发进阶。
187 0