接口不能直接new,但可通过匿名类或Lambda实例化;实现类必须implements并覆盖全部抽象方法;接口支持多继承,运行时引用类型不影响实际对象行为。

接口不能直接 new,但可以用匿名类或 Lambda 实例化
Java 中 interface 是纯抽象类型,编译器禁止写 new MyInterface()。但这不意味着它完全不能“变成对象”——只要提供所有抽象方法的实现,就能构造实例。
常见做法有两种:
- 用匿名内部类:适合方法较多、逻辑较重的场景,例如测试回调或临时策略
- 用 Lambda 表达式:仅限函数式接口(即有且仅有一个抽象方法),如
Runnable、Comparator、自定义的@FunctionalInterface
Runnable r = () -> System.out.println("hello");
Comparator c = (a, b) -> a.length() - b.length(); 注意:Lambda 本质是编译器生成的私有静态方法 + 内部类桥接,不是语法糖那么简单;过度嵌套或捕获大对象可能影响 GC。
实现类必须 implements 接口,且覆盖全部抽象方法
一个类要成为某接口的实现者,必须显式声明 implements InterfaceName,并在编译期满足契约:所有 public abstract 方法都有可访问的 public 实现(默认方法和静态方法不用覆写)。
立即学习“Java免费学习笔记(深入)”;
容易忽略的细节:
- 如果实现类是
abstract,可以不实现部分抽象方法 - 接口中
default方法可被重写,但子类若想调用父接口的默认实现,需用InterfaceName.super.method() - 多个接口含同签名
default方法时,实现类必须显式重写,否则编译报错:class inherits unrelated defaults for method from types
接口之间可用 extends,但只能单继承、可多继承
接口支持用 extends 继承其他接口,语法上允许一次写多个父接口,例如:interface A extends B, C, D。这和类的 extends(只允许一个)完全不同。
这种设计让接口能组合能力,比如:
interface Readable extends AutoCloseable {
String readLine();
}
interface Writable {
void write(String s);
}
interface TextFile extends Readable, Writable { }但要注意:若 B 和 C 都定义了同名同参的 default 方法,TextFile 编译不过,必须自己提供实现。
运行时无法区分「通过接口引用」还是「通过实现类引用」指向同一对象
Java 的多态发生在运行时,JVM 只看实际对象类型,不看变量声明类型。也就是说:MyInterface obj = new MyClass(); 和 MyClass obj = new MyClass(); 创建的是同一个对象,只是引用类型不同。
关键影响:
- 字段访问始终按引用类型决定(接口不能有实例字段,所以接口引用只能看到接口里定义的
public static final常量) - 方法调用走动态绑定:哪怕通过接口引用调用,最终执行的仍是实现类里重写的方法
- 强制转型(
(MyClass) obj)必须确保实际类型匹配,否则抛ClassCastException
这个机制是 Spring AOP、Mockito 动态代理等工具的基础——它们返回的往往是一个实现了目标接口的代理对象,你拿它当接口用完全没问题,但底层根本不是原实现类。










