个人主页→VON
收录专栏→java从入门到起飞
接口→接口和接口与抽象类综合案例
一、JDK8接口中新增的方法
在JDK 8中,接口新增了几个重要的特性和方法,其中最显著的是默认方法(Default Methods)和静态方法(Static Methods)。这些特性使得接口在Java编程语言中变得更加灵活和功能强大。
默认方法(Default Methods):
默认方法允许在接口中定义具体的方法实现,而不再是纯粹的抽象方法集合。主要特点包括:
- 实现方法:接口可以包含带有默认实现的方法体
- 兼容性:默认方法的引入不会破坏现有的接口实现,因为现有实现不需要强制重写新增的默认方法。
- 多继承冲突解决:如果一个类实现了多个接口,并且这些接口具有相同的默认方法,编译器会要求显式重写冲突的方法,以明确指定使用哪个接口的方法
注意事项:
1. 默认方法不是抽象方法,所以不强制重写,但是重写时别忘了去掉default关键字。
示例:
InterA接口
package com.von.day15b;public interface InterA {public default void showA(){System.out.println("showA");}
}
InterImpl类
package com.von.day15b;public class InterImpl implements InterA{@Overridepublic void showA() {System.out.println("重写showA");}
}
结果展示:
2. 定义默认方法时default不能省略。
3. 如果实现多个接口,并且多个接口中有相同的名字,子类就必须对该方法重写。
示例:
InterA
package com.von.day15b;public interface InterA {public default void showA(){System.out.println("A接口中的showA");}
}
InterB
package com.von.day15b;public interface InterB {public default void showA(){System.out.println("B接口中的showA");}public default void showB(){System.out.println("showB");}
}
InterImpl
package com.von.day15b;public class InterImpl implements InterA,InterB{}
结果展示:
静态方法(Static Methods):
接口中还可以定义静态方法,这些方法可以直接通过接口名调用,不需要实现类的实例。
接口中其他新增方法:
除了默认方法和静态方法,JDK 8中还新增了一些其他方法,以增强接口的功能:
-
函数式接口(Functional Interface):引入了
@FunctionalInterface
注解,用于标识函数式接口,即只包含一个抽象方法的接口。 -
接口中的方法可以有方法体:除了默认方法和静态方法外,还可以在接口中直接定义方法体的普通方法。
-
接口中方法的可访问性:接口中的方法可以是
public
或default
访问级别,不允许使用private
或protected
访问级别。
示例:
@FunctionalInterface
interface MathOperation {int operate(int a, int b);default void log() {System.out.println("MathOperation interface");}static void info() {System.out.println("Static method in MathOperation interface");}
}public class Main {public static void main(String[] args) {MathOperation addition = (a, b) -> a + b;MathOperation subtraction = (a, b) -> a - b;System.out.println(addition.operate(10, 5)); // 输出 15System.out.println(subtraction.operate(10, 5)); // 输出 5addition.log(); // 输出 "MathOperation interface"MathOperation.info(); // 输出 "Static method in MathOperation interface"}
}
在这个示例中,
MathOperation
接口定义了一个抽象方法operate
,一个默认方法log
,和一个静态方法info
。Main
类实现了函数式接口,并展示了如何使用接口的不同方法。
二、JDK9接口中新增的方法
JDK 9 在接口方面的改进相对于 JDK 8 并不多,但是在整体 Java 平台和语言的功能上有一些显著的变化和新增特性。
私有方法(Private Methods)
JDK 9 允许接口中定义私有方法,这些方法只能在接口内部使用,对实现类和其他类不可见。这使得接口能够更好地组织和重用代码逻辑。
interface MyInterface {default void publicMethod() {// 可调用私有方法privateMethod();}private void privateMethod() {// 接口内部私有方法的实现}
}
接口中的静态私有方法(Static Private Methods)
除了实例私有方法,JDK 9 还引入了接口中的静态私有方法,这些方法可以在接口的静态方法和默认方法中重复使用。
interface MyInterface {static void staticMethod() {// 可调用静态私有方法staticPrivateMethod();}private static void staticPrivateMethod() {// 接口内部静态私有方法的实现}
}
兼容性注解(@Deprecated, @DeprecatedSince)
JDK 9 引入了两个新的注解 @Deprecated
和 @DeprecatedSince
,用于指定一个方法或接口已被弃用以及自从哪个版本开始弃用。
@Deprecated(since="9.0")
interface MyDeprecatedInterface {@Deprecated(since="9.0")void deprecatedMethod();
}
三、接口的应用
接口在Java中是一种非常重要的概念,它提供了一种定义方法签名而不实现方法体的方式,这使得接口在Java编程中具有广泛的应用场景和优势。
实现多态: 接口允许类在不同的上下文中具有不同的行为。通过实现相同的接口,不同的类可以按照自己的方式实现接口中的方法,从而实现多态性,增加代码的灵活性和可扩展性。
interface Animal {void makeSound();
}class Dog implements Animal {public void makeSound() {System.out.println("Woof");}
}class Cat implements Animal {public void makeSound() {System.out.println("Meow");}
}
实现服务提供者接口: 接口可以用于定义服务的契约,不同的实现类可以提供不同的服务实现。这种模式在插件化和模块化系统中特别有用。
interface DatabaseConnector {void connect();
}class MySQLConnector implements DatabaseConnector {public void connect() {System.out.println("Connecting to MySQL database...");}
}class PostgreSQLConnector implements DatabaseConnector {public void connect() {System.out.println("Connecting to PostgreSQL database...");}
}
解耦合: 接口有助于解耦合,即减少代码间的依赖性。程序员可以编写针对接口的代码,而不是具体的实现类,从而使得代码更容易维护和扩展。
interface Logger {void log(String message);
}class FileLogger implements Logger {public void log(String message) {// Log message to file}
}class ConsoleLogger implements Logger {public void log(String message) {// Log message to console}
}
实现回调机制: 接口可以用于实现回调机制,即某个对象在特定事件发生时调用另一个对象的方法。这在事件驱动编程和异步处理中非常常见。
interface Callback {void onComplete(String result);
}class Task {void execute(Callback callback) {// Perform some task and invoke callbackcallback.onComplete("Task completed successfully");}
}
函数式接口和Lambda表达式: Java 8 引入了函数式接口的概念,即只包含一个抽象方法的接口。这种接口可以用Lambda表达式来实现,提供了更加简洁和灵活的函数式编程方式。
@FunctionalInterface
interface MyFunction {void perform();
}public class Main {public static void main(String[] args) {MyFunction func = () -> System.out.println("Performing function");func.perform();}
}
四、适配器设计模式
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的对象可以相互合作。适配器模式通常用于旧接口与新系统之间的适配,或者不同接口之间的适配。
结构和角色
适配器模式涉及以下几个角色:
-
目标接口(Target): 目标接口是客户端期待使用的接口。客户端通过目标接口与适配器交互,调用在目标接口中定义的方法。
-
适配器(Adapter): 适配器实现了目标接口,并且包装了一个被适配者(Adaptee)。它将客户端的请求转换为对被适配者的相应调用。
-
被适配者(Adaptee): 被适配者是原本存在的接口,但它与客户端要求的接口不兼容。适配器通过包装被适配者,使其与客户端能够兼容。
工作原理和应用场景
适配器模式的工作原理是通过创建一个中间层(适配器),将客户端的请求转换为被适配者可以理解的请求。这种模式常见于以下几种情况:
-
系统升级与兼容:当系统进行升级或者集成时,可能需要与旧系统进行适配,以保证新旧系统能够无缝衔接。
-
第三方库或组件的使用:当使用第三方库或组件时,其接口可能与当前系统的接口不匹配,需要通过适配器进行适配。
-
接口的转换:当需要将一个接口转换成另一个接口时,可以使用适配器模式。
示例:
// 目标接口
interface Smartphone {void charge();
}// 被适配者(电子书阅读器)
class EBookReader {void powerOn() {System.out.println("EBookReader is powering on.");}void turnPage() {System.out.println("EBookReader is turning the page.");}
}// 适配器
class EBookReaderAdapter implements Smartphone {private EBookReader reader;EBookReaderAdapter(EBookReader reader) {this.reader = reader;}@Overridepublic void charge() {reader.powerOn();System.out.println("Charging EBookReader...");}
}// 客户端代码
public class Client {public static void main(String[] args) {EBookReader kindle = new EBookReader();Smartphone smartphone = new EBookReaderAdapter(kindle);smartphone.charge(); // 使用智能手机充电}
}
在上面的示例中,
EBookReader
是被适配者,它有自己的一些方法,但是没有charge()
方法。通过EBookReaderAdapter
适配器,我们实现了Smartphone
接口,并在charge()
方法中调用了EBookReader
的方法,从而将其适配成了一个智能手机可以使用的接口。