骨架与能力:一文吃透 Java 抽象类、接口、内部类及实战模式

一、抽象类:把公共骨架抽出来

  1. 关键字 abstract

    • 不能实例化;

    • 可包含抽象方法(无方法体)和普通成员;

    • 子类必须补全所有抽象方法,否则也得声明为抽象。

  2. 强制让子类实现某方法

    方案一:运行时抛 UnsupportedOperationException(不推荐,编译期不报错)。

    方案二:直接声明抽象方法,编译器帮你兜底。

二、接口:只描述能力,不提供实现

  1. 基本语法

    java 复制代码
    public interface 会飞 {
        void 飞();   // 默认 public abstract
    }

    实现类:

    java 复制代码
    public class 鸟 extends 动物 implements 会飞, 会呼吸 {
        @Override public void 飞() { System.out.println("鸟儿飞"); }
    }

    • 支持多继承,解决菱形问题;

    • 成员变量默认 public static final

  2. Java 8 后的默认方法

    java 复制代码
    interface List<E> {
        default void sort(Comparator<? super E> c) { ... }
    }

    带来便利的同时也可能出现"二义性",类优先原则或显式 X.super.f() 解决。

  3. 向后兼容

    接口一旦发布很难改,默认方法可在不破坏旧实现的前提下扩展功能。

三、抽象类 vs 接口

维度 抽象类 接口
继承/实现 单继承 多实现
构造器
成员变量 任意 仅 public static final
方法 可有实现 默认无实现(8 后支持 default)
设计语义 is-a,模板 has-a,能力

口诀:

"模板用抽象,能力用接口;多继承场景一定用接口。"

四、实战 1:文件过滤器

需求:递归查找指定后缀的文件。

• 第一版:独立 FileFilterVisitor 继承 SimpleFileVisitor<Path>

• 第二版:匿名内部类,把逻辑收拢,减少参数传递。

java 复制代码
Files.walkFileTree(root, new SimpleFileVisitor<>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        if (file.toString().endsWith(ext)) names.add(file.getFileName());
        return CONTINUE;
    }
});

五、实战 2:Comparable 与策略模式

Comparable<T> 就是策略接口,sort 方法内部使用 compareTo 决定顺序。

TreeSet 依赖 compareTo 判断相等,若比较器写错会导致元素"丢失"。

原则:不同对象绝不能让 compareTo 返回 0。

六、Predicate ------ JDK 自带"判断"策略

java 复制代码
Predicate<String> p = s -> s.endsWith(".csv");

可组合 and/or/negate,配合 Stream 一行搞定过滤。

七、内部类与匿名类

  1. 种类

    • 成员内部类(非 static):隐式持有外部类实例。

    • 静态内部类:不持有外部引用,可独立存在。

    • 局部/匿名内部类:常见于回调、一次性实现。

  2. 面试问答

    Q:private classprivate static class 区别?

    A:前者需要外部实例,后者不需要,也不会造成隐式内存泄漏。

  3. 最佳实践

    永远优先使用 static 内部类,除非必须访问外部实例字段。匿名类编译后生成 $1$2 字节码文件,调试时注意。

八、小结与 checklist

• 需要"模板"→抽象类;需要"能力"→接口。

• 多实现、多继承场景→接口。

• 默认方法谨慎使用,避免二义性。

• 内部类默认加 static,防止内存泄漏。

• 匿名类适合一次性策略实现,代码紧凑。

相关推荐
paopaokaka_luck2 小时前
基于SpringBoot+Uniapp的健身饮食小程序(协同过滤算法、地图组件)
前端·javascript·vue.js·spring boot·后端·小程序·uni-app
Villiam_AY2 小时前
Redis 缓存机制详解:原理、问题与最佳实践
开发语言·redis·后端
魔尔助理顾问6 小时前
系统整理Python的循环语句和常用方法
开发语言·后端·python
程序视点6 小时前
Java BigDecimal详解:小数精确计算、使用方法与常见问题解决方案
java·后端
你的人类朋友6 小时前
❤️‍🔥微服务的拆分策略
后端·微服务·架构
AI小智8 小时前
后端变全栈,终于可以给大家推出我的LangChain学习小站了!
后端
lkf197118 小时前
商品中心—1.B端建品和C端缓存
开发语言·后端·缓存
我的ID配享太庙呀9 小时前
Django 科普介绍:从入门到了解其核心魅力
数据库·后端·python·mysql·django·sqlite
java叶新东老师9 小时前
goland编写go语言导入自定义包出现: package xxx is not in GOROOT (/xxx/xxx) 的解决方案
开发语言·后端·golang
码事漫谈11 小时前
C++模板元编程从入门到精通
后端