官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
我的理解:接口可以理解为一种特殊的抽象类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,可以实现多个接口的实现,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,接口中的方法必须全部是抽象方法。
一、接口的基本概念与主要特点;
二、接口的使用;
三、接口应用:简单工厂设计模式、代理设计模式简单实现。
1.1 接口特点
就像一个类一样,一个接口也能够拥有方法和属性,但是在接口中声明的方法默认是抽象的。(即只有方法标识符,而没有方法体)。
一个JAVA库中接口的例子是:Iterator 接口,这个接口代表了“能够进行迭代遍历”这种能力,任何类只要实现了这个 “ Iterator” 接口的话,这个类也具备了 “迭代遍历” 这种能力,那么就可以用来进行元素遍历操作了。
1.2 为什么要用接口
2.1 接口的定义
要定义一个接口使用 interface 关键字完成。
interface A{ // 定义接口
public static final String MSG="hello";
// 抽象方法
public abstract void print();
}
由于接口里面存在有抽象方法,所以接口对象不能用关键字new进行实例化的操作。先说几个接口使用的限制:
范例:实现接口
interface A { // 定义了接口
public static final String MSG = "hello";
// 抽象方法
public abstract void print();
}
interface B {
public abstract void get();
}
class X implements A,B { // 实现多个接口
public void get() {
System.out.println("B接口的抽象方法");
}
public void print() {
System.out.println("A接口的抽象方法");
}
}
public class TestDemo {
public static void main(String args[]){
X x = new C();//实例化子类对象
A a = x;
B b = x;
// A a = new X();//向上转型
// B b = new X();//向上转型
a.print();
b.get();
}
}
以上的代码实例化了 “x” 对象,由于 X 是 A 和 B 的子类,那么 X 类对象可以变为 A 接口或 B 接口类的对象。
在定义上 A 和 B 接口没有任何的直接联系,但是这两个接口却同时拥有一个子类: X 子类,不要被类型和名称所迷惑,因为最终实例化的 X 的子类,而这个子类属于 B 类的对象,所以以上的代码行的通,代码编写上并不是很友好。
2.2 子类继承和接口实现使用
代码示例(即有继承关系又有接口实现)
interface A { // 定义了接口
public static final String MSG = "hello";
// 抽象方法
public abstract void print();
}
interface B {
public abstract void get();
}
abstract class C { // 定义一个抽象类
public abstract void change();
}
class X extends C implements A,B {//先继承,再实现接口
public void get() {
System.out.println("B接口的抽象方法");
}
public void print() {
System.out.println("A接口的抽象方法");
}
public void change(){
System.out.println("C类的抽象方法");
}
}
对接口而言,发现里面的组成是抽象方法和全局变量,所以很多的时候有些人为了简略不会写 abstract 和 public static final,并且在方法上是否编写 public 结果都是一样的,因为在接口里面只能够使用一种访问权限——public。以下两个接口的定义效果是一样的:
interface A{
public static final String MSG="HELLO";
public void fun();
}
// 另一种定义方式 ,常量的话 我们 一般 写成 public static final String MSG = “Hello”;
Interface A{
String MSG=”HELLO”;
void fun();
}
一个抽象类可以继承一个抽象类,一个接口可以使用extends关键字同时继承多个接口,接口不可以继承抽象类。
2.3 接口的多继承
范例:接口的多继承
interface A {
public void funA();
}
interface B {
public void funB();
}
interface C extends A,B {
public void funC();
}
class X implements C {
public void funA() { } // 覆写全部的方法
public void funB() { }
public void funC() { }
}
从继承关系上讲接口比抽象类的优势明显:
2.4 在接口中定义抽象类和 static 接口
范例:在接口里定义抽象类
interface A{
public void funA();
// 独立的class文件,
abstract class B{
// 在接口中的abstract可以不用写,但在抽象类中的抽象方法必须要写abstract
public abstract void funB();
}
interface Entry { // 接口中定义接口 ,Map.Entry HashMap 源码 Collection 中的 Iterator 接口
}
}
class X implements A { // X 实现了A接口
public void funA() {
System.out.println("Hello World");
}
class Y extends B { // 内部类 Y继承了抽象类 B 实现了 funB() 方法
public void funB () {
System.out.println("hello C");
}
}
}
在接口中定义static接口
interface A {
public void funA();
// static声明的内部接口为外部接口,static声明的内部类为外部类
static interface B{ // 外部接口,
public void funB();
}
}
class X implements A.B{ // 实现时使用“类名.内部接口”
public void funB() {
}
先期总结:接口在实际的开发中三大核心作用:
2.5 接口中的实际应用——标准
电脑上可以使用U盘、Mp3、打印机,这些设备都是连接到USB设备上的。
范例:定义USB标准(标准可以连接不同层的操作)
// 标准可以连接不同层的操作
interface USB { // 定义标准一定是接口
public void start();
public void stop();
}
范例:定义电脑
不管以后有多少个设备,只要它是 USB 标准的实现子类,它都可以在电脑上使用。
class Computer {
public void plugin(USB usb){//插入
usb.start();
usb.stop();
}
}
范例:定义U盘
class Flash implements USB {
public void start(){
System.out.println("U盘开始使用");
}
public void stop(){
System.out.println("u盘停止使用");
}
}
范例:定义打印机
class Print implements USB {
public void start(){
System.out.println("打印机开始工作");
}
public void stop(){
System.out.println("打印机停止工作");
}
}
按照这样的方式,准备好多个子类都可以在电脑的plugin()方法上使用
interface USB{//定义标准一定是接口
public void start();
public void stop();
}
class Computer {
public void plugin(USB usb){//插入
usb.start();
usb.stop();
}
}
class Flash implements USB{
public void start(){
System.out.println("U盘开始使用");
}
public void stop(){
System.out.println("u盘停止使用");
}
}
class Print implements USB{
public void start(){
System.out.println("打印机开始工作");
}
public void stop(){
System.out.println("打印机停止工作");
}
}
public class TestDemo {
public static void main(String args[]){
Computer com = new Computer();
com.plugin(new Flash());
com.plugin(new Print());
}
}
在现实生活中,标准的概念随处可见,而在程序里面标准就是用接口来实现的。
3.1 接口的应用——工厂设计模式(Factory 简单介绍)
下面观察一段程序代码
interface Fruit {
public void eat();
}
class Apple implements Fruit {
public void eat() {
System.out.println("吃苹果");
}
}
public class TestDemo {
public static void main(String args[]){
Fruit f = new Apple();
f.eat();
}
以上的程序可以通过主方法得到Fruit接口对象,这种代码设计有问题吗?
本端程序的问题就是出现了关键字“new”。
评判一段代码是否真的好,有这么几个标准:
客户端可以调用,不需要关注具体的细节;
客户端之外的代码修改,不影响用户端的使用,即:用户端可以不关
心代码是否变更。
一个接口不可能只有一个子类,对于Fruit也有可能产生多个子类对象(Apple,Orange)。
现在每次客户端想要得到新的子类对象,都需要修改代码,如果在客户端实例化对象,那么每一要更换对象对象,都需要修改客户端上的代码,这样的做法是不友好的。
现在要解决是如何得到一个Fruit接口对象,而后进行方法的调用,至于这个接口对象是被谁实例化的,不是我客户端的工作。现在最大的问题在于关键字new,这一问题可以理解为耦合度太高。耦合度太高的直接问题就是代码不方便维护,相当于A与B绑定在一起。
程序 -> JVM -> 适应不同的操作系统(A->C->B)
范例:增加一个过渡
class Factory {
public static Fruit getInstance(String className){
if ("apple".equals(className)) {
return new Apple();
} else if ("orange".equals(className)) {
return new Orange();
} else {
return null;
}
}
}
public class TestDemo {
public static void main(String args[]){
Fruit f = Factory.getInstance("apple");
f.eat();
}
}
工厂类跟操作的接口类有关,也跟所有的子类有关;客户端可看见接口,还可以看见工厂,客户端使用getInstance()方法找到工厂类中定义的方法,这个方法返回接口对象,通过接口对象就可以获得接口中的操作方法。
面试题:请编写一个Factory程序
3.2 接口的应用——代理设计模式(Proxy简单介绍)
皇帝宠幸妃子的为例,具体步骤图中已经列出。
范例:转换为程序
interface Subject { // 整个操作的核心
public void makeLove(); // 整个临幸的核心功能
}
class RealSubject implements Subject { // 一个接口两个主题
public void makeLove() {
System.out.println("正在");
}
}
class ProxySubject implements Subject {//内务
private Subject subject;
// 要接受一个真正主题的操作对象
public ProxySubject(Subject subject){
this.subject = subject;
}
public void prepare(){ // 扩展的功能
System.out.println("为临幸做准备");
}
public void makeLove() {
this.prepare();
this.subject.makeLove(); // 告诉皇帝可以开始了
this.end();
}
public void end() { // 扩展的功能
System.out.println("娘娘带走,皇帝睡觉");
}
}
public class TestDemo {
public static void main(String args[]){
Subject sub = new ProxySubject(new RealSubject());
sub.makeLove();//调用的是代理操作
}
}
代理模式的主要角色如下。
使用代理(静态代理)的目的和缺陷:
缺点:
面试题:请编写一个Proxy模式程序
抽象类和接口使用的形式上是十分相似的。
4.1 表格对比
4.2 文字描述
接口与抽象类的区别:
代码编写的习惯:
参考文档:https://www.cnblogs.com/qmdx00/p/7469379.html
https://blog.csdn.net/qq_19782019/article/details/80259836
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_43842093/article/details/123022956
内容来源于网络,如有侵权,请联系作者删除!