接口的基础与使用
实现类与接口文件结构
笔者在开发中常使用接口来定义统一的行为规范。接口文件通常以 I 开头并采用驼峰命名方式。接口文件和类文件的后缀都为.java。一个类的实现类往往在类名后添加 Impl 作为标识,方便快速识别该类实现了对应接口的约定。
下面的代码展示了一个接口 IMyInterface 的简单实现类。接口本身无法实例化,必须通过实现类来完成实例化操作。
package com.oop_5;
public interface IMyInterface {
}
package com.oop_5;
public class MyInterfaceImpl implements IMyInterface {
}
接口的特性
笔者理解接口是定义一组特定行为的公共规范。当笔者为某个功能模块创建接口时,会为类指定统一的行为约束,使得不同类都能实现相同的方法签名,实现模块化与可扩展性。
接口在 Java 7 时期只允许包含常量与抽象方法。常量必须在定义时赋值,且默认是 public static final。抽象方法默认是 public abstract,并且没有方法体。
到了 Java 8,接口中可以包含默认方法与静态方法。默认方法使用 default 关键字,在实现类不做额外实现的情况下,即可使用该方法,方便在不破坏已有实现类的前提下扩展接口。静态方法必须通过接口名调用,与实现类无关。
在 Java 9 中,接口还可以包含私有方法。这些方法只能在接口内部使用,主要是为默认方法或静态方法提供内部逻辑支持,不对外公开。
笔者在命名接口时习惯以 I 开头,并使用驼峰命名法,以确保代码风格统一。接口无法被实例化,只能通过实现类来创建对象。实现类必须实现接口中的所有抽象方法,如果实现类是抽象的,则可以不实现这些方法,但最终的具体类需要完成所有方法的实现。
示例代码
下面展示一个功能更完整的接口示例。笔者在此接口中定义了抽象方法、默认方法、静态方法以及私有方法。同时也包括常量定义。实现类在实现接口时,需要根据实际需求实现这些抽象方法和可能覆盖默认方法。
public interface IMyInterface {
// 抽象方法
public abstract void abstractMethod1();
// 默认方法
public default void defaultMethod1() {
System.out.println("defaultMethod1");
}
public default void defaultMethod2() {
privateMethod1("私有方法1");
System.out.println("defaultMethod2");
}
public default void defaultMethod3() {
privateMethod1("私有方法2");
System.out.println("defaultMethod3");
}
// 静态方法
public static void staticMethod1() {
System.out.println("staticMethod1");
}
// 私有方法(Java 9及之后版本)
private void privateMethod1(String content) {
System.out.println(content);
}
// 接口常量,默认public static final
String CONSTANT1 = "常量1";
String CONSTANT2 = "常量2";
String CONSTANT3 = "常量3";
String CONSTANT4 = "常量4";
}
接口和抽象类的关系
笔者在实践中注意到类的继承是单一的,一个类只能有一个父类,但是可以实现多个接口。这使得接口成为一种灵活的扩展方式。类若未使用 extends 关键字继承其他类,则默认继承自 Object 类。一个类可以同时实现多个接口,用逗号分隔多个接口名称。
实现类必须实现接口中所有的抽象方法。如果实现类是抽象类,可以暂时不实现接口的抽象方法,直到有具体类继承这抽象类并完成实现为止。若父类的某个方法已实现了接口中的抽象方法,那么子类可直接利用该实现。
当多个接口中存在同名的默认方法时,实现类必须重写该方法以避免冲突。如果父类和接口中的默认方法同名,那么调用时会优先使用父类的方法。继承优先于接口实现是 Java 的基本原则。
静态方法与默认方法的区别
笔者在使用接口时关注到静态方法与默认方法是截然不同的概念。静态方法属于接口本身,可通过接口名直接调用,与类实例无关。默认方法则是为了给接口添加新功能时不影响已有实现类而设计的,默认方法在实现类中可直接使用,也可被覆盖。默认方法实现的是面向扩展的设计思路,静态方法则多用于提供通用工具逻辑。
注意事项
笔者建议在设计接口时确保接口方法的命名清晰易懂,参数与返回值定义明确。同时要保持接口方法的数量在合理范围内,避免接口过于冗杂。默认方法在扩展既有接口时非常实用,但应审慎使用,确保其存在确有必要。通过合理使用接口与抽象类,可以有效提升代码结构的清晰度与扩展性。