当前位置: 首页 > news >正文

JavaSE面向对象(下)

抽象类的定义

  • 使用 abstract 关键字修饰类:

    abstract class AbstractPlayer {}
    
  • 按规范,抽象类命名应以 AbstractBase 开头(如:AbstractPlayerBaseService)。

抽象类的特征

  1. 不能被实例化

    AbstractPlayer player = new AbstractPlayer(); // ❌ 编译错误
    
  2. 可以被继承:子类使用 extends 继承抽象类

    public class BasketballPlayer extends AbstractPlayer {}
    
  3. 包含抽象方法

    抽象方法必须在抽象类中定义
    抽象方法没有方法体,只定义方法签名
    子类必须实现父类中的所有抽象方法,否则子类也必须是抽象类

    abstract void play();
    
  4. 可以包含普通方法:抽象类可以混合抽象与非抽象方法

    public abstract class AbstractPlayer {abstract void play();public void sleep() {System.out.println("运动员也要休息");}
    }
    

抽象类的应用场景

1️⃣ 代码复用场景

  • 抽象类可以定义多个子类共有的功能(如 sleep() 方法),避免重复代码。
  • 子类继承后可以直接使用这些公共方法。

2️⃣ 统一接口、延迟实现场景

  • 抽象类可作为一种模板或框架,规定子类必须实现的功能。

  • 例如:play() 方法定义了所有运动员都要“从事某项运动”的行为,但不同子类各自实现不同内容。

    abstract class AbstractPlayer {abstract void play();
    }
    

抽象类的进阶示例:文件读取器

基类定义(模板模式思想)

abstract class BaseFileReader {protected Path filePath;protected BaseFileReader(Path filePath) {this.filePath = filePath;}public List<String> readFile() throws IOException {return Files.lines(filePath).map(this::mapFileLine).collect(Collectors.toList());}protected abstract String mapFileLine(String line);
}
  • readFile() 定义了文件读取的整体流程。
  • mapFileLine() 是一个钩子方法(由子类实现不同转换逻辑)。

子类实现不同的读取方式

class LowercaseFileReader extends BaseFileReader {@Overrideprotected String mapFileLine(String line) {return line.toLowerCase();}
}class UppercaseFileReader extends BaseFileReader {@Overrideprotected String mapFileLine(String line) {return line.toUpperCase();}
}

测试类

public class FileReaderTest {public static void main(String[] args) throws Exception {URL location = FileReaderTest.class.getClassLoader().getResource("helloworld.txt");Path path = Paths.get(location.toURI());BaseFileReader lower = new LowercaseFileReader(path);BaseFileReader upper = new UppercaseFileReader(path);System.out.println(lower.readFile());System.out.println(upper.readFile());}
}

抽象类的总结

特征说明
实例化不可直接实例化
方法类型可包含抽象方法与普通方法
子类要求必须实现所有抽象方法或自身声明为抽象类
用途代码复用、定义模板、约束子类行为

核心思想

抽象类是“模板”与“约束”的结合。

它既能封装通用逻辑(复用代码),又能通过抽象方法约束子类实现特定行为。

接口的定义与语法

  • 使用 interface 关键字定义接口:

    public interface Electronic {String workconsistent = "workconsistent";                  // 常量int getElectricityUse();             // 抽象方法static boolean isEnergyEfficient(String type) { ... } // 静态方法 (Java 8+)default void printDescription() { ... }               // 默认方法 (Java 8+)
    }
    

接口成员特征

成员类型默认修饰符说明
变量public static final即常量,值不可修改
抽象方法public abstract无方法体,需由实现类实现
静态方法public static需用接口名调用,不可由实例调用
默认方法public default可有方法体,供实现类直接复用

接口可包含静态方法与默认方法,用以增强接口的扩展性和兼容性。

接口的限制与特性

  1. 接口 不能被实例化,必须由类通过 implements 实现:

    public class Computer implements Electronic { ... }
    
  2. 接口 不能使用 final 修饰(否则无法被实现)。

  3. 抽象方法 不能是 privateprotectedfinal

  4. 接口变量是常量(public static final),值不可修改

  5. 接口可以是空接口(标记接口),如:

    public interface Serializable {}
    

    实现该接口的类具有某种“标识性”功能(例如可被序列化)。

接口的作用

1️⃣ 提供功能约定

实现接口的类具有特定功能,例如:

  • Cloneable → 支持克隆
  • Serializable → 支持序列化
  • Comparable / Comparator → 支持比较

示例:Cloneable 接口

public class CloneableTest implements Cloneable {@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}

2️⃣ 支持多重继承

Java 不支持类的多继承,但接口可以实现“多继承行为”:

public interface Fly { void fly(); }
public interface Run { void run(); }public class Pig implements Fly, Run {public void fly() { System.out.println("会飞的猪"); }public void run() { System.out.println("会跑的猪"); }
}

一个类可实现多个接口,避免了“菱形继承问题”。

3️⃣ 实现多态(Polymorphism)

通过接口引用不同实现类,实现同一方法不同表现

interface Shape { String name(); }class Circle implements Shape {public String name() { return "圆"; }
}
class Square implements Shape {public String name() { return "正方形"; }
}List<Shape> shapes = List.of(new Circle(), new Square());
for (Shape s : shapes){// 圆、正方形System.out.println(s.name());
}

多态的三个前提

  1. 有继承或实现关系;
  2. 子类重写父类或接口方法;
  3. 父类引用指向子类对象。

接口的三种典型设计模式

策略模式(Strategy Pattern)

  • 定义一组算法(策略)并封装,调用方通过接口使用不同实现。
// 策略模式示例:多种支付方式// 1. 定义支付策略接口
interface PaymentStrategy {void pay(double amount);
}// 2. 定义不同的支付策略实现
class AlipayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("使用支付宝支付 " + amount + " 元");}
}class WeChatPayStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("使用微信支付 " + amount + " 元");}
}class CreditCardStrategy implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("使用信用卡支付 " + amount + " 元");}
}// 3. 支付上下文类,负责调用具体策略
class PaymentContext {private PaymentStrategy paymentStrategy;public PaymentContext(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void executePayment(double amount) {paymentStrategy.pay(amount);}
}// 4. 测试类(主程序)
public class StrategyDemo {public static void main(String[] args) {PaymentContext alipayContext = new PaymentContext(new AlipayStrategy());PaymentContext wechatContext = new PaymentContext(new WeChatPayStrategy());PaymentContext creditContext = new PaymentContext(new CreditCardStrategy());alipayContext.executePayment(199.99);wechatContext.executePayment(88.88);creditContext.executePayment(500.00);}
}

适配器模式(Adapter Pattern)

  • 用抽象类实现接口并置空方法,新类继承该抽象类,只需覆盖必要方法。
//  定义播放器接口
interface MediaPlayer {void playMp3(String fileName);void playMp4(String fileName);void playFlac(String fileName);
}//  抽象适配器类:实现接口但提供空方法(防止子类必须实现所有方法)
abstract class MediaAdapter implements MediaPlayer {public void playMp3(String fileName) {}public void playMp4(String fileName) {}public void playFlac(String fileName) {}
}//  子类根据需要只实现自己关心的方法
class Mp3Player extends MediaAdapter {@Overridepublic void playMp3(String fileName) {System.out.println(" 正在播放 MP3 文件:" + fileName);}
}class Mp4Player extends MediaAdapter {@Overridepublic void playMp4(String fileName) {System.out.println(" 正在播放 MP4 文件:" + fileName);}
}class FlacPlayer extends MediaAdapter {@Overridepublic void playFlac(String fileName) {System.out.println(" 正在播放 FLAC 文件:" + fileName);}
}//  测试类
public class AdapterDemo {public static void main(String[] args) {MediaPlayer mp3 = new Mp3Player();MediaPlayer mp4 = new Mp4Player();MediaPlayer flac = new FlacPlayer();mp3.playMp3("周杰伦 - 晴天.mp3");mp4.playMp4("电影 - 功夫.mp4");flac.playFlac("林俊杰 - 江南.flac");}
}

工厂模式(Factory Pattern)

  • 定义接口规范产品与工厂,通过不同工厂创建不同对象。
//  图形接口
interface Shape {void draw();
}//  具体图形类:圆形、矩形、三角形
class Circle implements Shape {@Overridepublic void draw() {System.out.println("正在画一个圆形 🟢");}
}class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("正在画一个矩形 🟥");}
}class Triangle implements Shape {@Overridepublic void draw() {System.out.println("正在画一个三角形 🔺");}
}//  抽象工厂接口
interface ShapeFactory {Shape createShape();
}//  具体工厂类
class CircleFactory implements ShapeFactory {@Overridepublic Shape createShape() {return new Circle();}
}class RectangleFactory implements ShapeFactory {@Overridepublic Shape createShape() {return new Rectangle();}
}class TriangleFactory implements ShapeFactory {@Overridepublic Shape createShape() {return new Triangle();}
}//  测试类
public class FactoryDemo {// 静态方法,接收不同的工厂对象public static void drawShape(ShapeFactory factory) {Shape shape = factory.createShape();shape.draw();}public static void main(String[] args) {drawShape(new CircleFactory());drawShape(new RectangleFactory());drawShape(new TriangleFactory());}
}

抽象类 vs 接口

对比点抽象类接口
关键字abstract classinterface
是否可包含实现可包含具体方法仅方法声明
成员变量任意类型public static final 常量
静态代码块可以不允许
继承 / 实现数量单继承多实现
设计目的的抽象(模板式设计)行为的抽象(规范式设计)
关系表达“是一个(is-a)”“具有……能力(has-a)”
修改影响改抽象类 → 子类不一定改改接口 → 所有实现类需同步改动

接口是行为规范,抽象类是模板设计。

  • 接口 关注“能力”,强调“能做什么”;
  • 抽象类 关注“共性”,强调“是什么”;
  • 抽象类提供“部分实现”,接口提供“统一约定”;
  • 接口支持多继承,抽象类支持代码复用。

内部类的四种类型

成员内部类

定义在外部类的成员位置,没有使用 static 修饰。

public class Icheng {private String hobby = "写代码";static int age = 25;class Friend {public void introduce() {System.out.println("一成的爱好是:" + hobby);System.out.println("一成今年:" + age + " 岁");}}public static void main(String[] args) {Icheng icheng = new Icheng();Icheng.Friend friend = icheng.new Friend();friend.introduce();}
}

要点:

  • Friend 是成员内部类。

  • 可以访问外部类的:

    • 私有成员变量 hobby
    • 静态成员变量 age
  • 创建方式:外部类对象.new 内部类()

局部内部类

public class IchengCafe {private String cafeName = "一成的下午茶屋";public void closeCafe() {// 局部内部类:用于记录当天的结算信息class DailyReport {private int customers = 42;private double income = 589.5;public void printReport() {System.out.println(" 店铺:" + cafeName);System.out.println(" 今日接待顾客数:" + customers);System.out.println(" 今日营业额:" + income + " 元");}}// 在方法内创建并使用局部内部类对象DailyReport report = new DailyReport();report.printReport();}public static void main(String[] args) {IchengCafe cafe = new IchengCafe();cafe.closeCafe();//  店铺:一成的下午茶屋  // 今日接待顾客数:42// 今日营业额:589.5 元}
}

说明:

  • DailyReport 定义在 closeCafe() 方法内部,只能在此方法中使用。
  • 生命周期与 closeCafe() 方法一致,方法执行完就销毁
  • 不能使用 publicprivateprotectedstatic 修饰。
  • 常用于在方法中临时封装逻辑或实现接口。

3️⃣ 匿名内部类

没有名字的内部类,常用于简化
一次性类的使用(尤其是回调和线程)。

public class ThreadDemo {public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});t.start();}
}

特征与要点:

  • 无类名、无构造方法。
  • 直接通过 new 接口/父类() 创建对象并重写方法。
  • 常用于:事件监听、线程、回调等。
  • 本质上是一个语法糖,用于快速定义临时子类或实现类。

4️⃣ 静态内部类

public class Icheng {static int age = 21;double money = 99.9;static class Friend {public Friend() {// 21System.out.println(age);   // ✅ 可以访问外部类静态成员// System.out.println(money); ❌ 非静态成员不能访问}}public static void main(String[] args) {new Friend(); // 直接创建静态内部类对象}
}

说明:

  • Friend静态内部类,与外部类 Icheng 没有实例绑定关系。
  • 可以直接访问外部类的 静态变量 age
    但不能访问 非静态变量 money
  • 创建方式简洁:new Icheng.Friend() 或在同类中直接 new Friend()

使用内部类的原因与优势

💬 引用《Think in Java》:
“使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现。”

内部类的优势

  1. 实现多重继承效果
    内部类可以在外部类继承某个类的同时,实现另一个接口或类的功能。
  2. 实例独立性
    每个内部类对象都可拥有自己的状态,与外部类实例独立。
  3. 多样实现同一接口
    在一个外部类中,可以有多个内部类分别以不同方式实现同一个接口。
  4. 延迟创建
    内部类对象可在任意时刻创建,不依赖外部类的初始化。
  5. 更好的封装性
    内部类可隐藏实现细节,对外部完全不可见。

对比表

类型定义位置是否静态是否依附外部类对象可访问外部类成员修饰符限制使用场景
成员内部类外部类成员处所有成员无限制外部类的辅助逻辑
局部内部类方法/作用域内可访问局部变量(final 或 effectively final)不能用 public/private/protected/static方法内临时使用
匿名内部类表达式内可访问外部成员无修饰符简化接口或抽象类实现
静态内部类外部类成员处仅可访问静态成员可用 public/private/protected辅助类、工具类、Builder 模式

核心思想

内部类 = 一种在类中再定义类的机制,强化封装、灵活扩展。

  • 成员内部类 → 外部类的“成员”
  • 局部内部类 → 方法的“局部变量”
  • 匿名内部类 → 一次性“快捷实现类”
  • 静态内部类 → 独立于外部类存在的“嵌套类”
http://www.dtcms.com/a/496153.html

相关文章:

  • 网站怎么做前台跟后台的接口小说网站推广方式
  • Node.js v25 重磅发布!革新与飞跃:深入探索 JavaScript 运行时的未来
  • 2一、u-boot下载编译
  • C++ MFC控件实现小型通讯录
  • 东莞网站优化一般多少钱深圳网站seo优化公司
  • 免费制作app生成器网站馆陶网站建设电话
  • 从发币到行为经济:BSC 发币工具演化的下一站
  • 优秀企业网站wordpress导航怎么设置
  • 自己的主机做服务器网站如何备案企业融资流程
  • 通过强化学习让多模态大模型自主决策图像token压缩的新范式-VisionThink实现思路及奖励函数设计
  • 【C++】深入理解vector(1):vector的使用和OJ题
  • 前端最新Vue2+Vue3基础入门到实战项目9-10
  • UC3842/3845/2842/2845 软启动
  • 免费推广产品的网站年报申报入口官网
  • 做网站答辩三网合一营销型全网站
  • (定时任务)@Scheduled 到 XXL-Job:两种定时任务机制的核心区别
  • 【VSCode】Visual Studio Code 2024安装包及安装教程 (附所有版本下载)
  • java17中,使用原生url connection的方式去创建的http链接,使用的是http1.1还是2.0?
  • 无人机激光避障技术概述
  • 网站空间带宽t型布局网站的样子
  • 【测试】Web安全测试与自动化筛查
  • 上海黄浦 网站建设wordpress图床首页无缩略图
  • 免费手机建站平台杭州最大定制app开发公司
  • asp做的网站后台怎么进去wordpress文章推送公众号
  • Scrapy vs Requests:什么时候该用哪个爬虫框架?
  • 网站建设的步骤是什么赣州58同城网
  • 我的钢铁网网站架构jsp语言做网站
  • JavaSE基础——第十一章 常用类(一)
  • 建设网站托管费用wap手机网站描述正确的是
  • linux问题定位之寄存器篇