javaSE基础-接口

接口(Interface)

使用 implements 关键字使一个类遵循某个特定接口(或一组接口),它表示:接口只是外形。

接口决定方法名、参数列表和返回类型,但是无法确定方法体。接口只提供形式,通常来说 没有实现(JDK7及以前),尽管在某些受限制的情况下可以有实现。

Java 8 中接口稍微有些变化,因为 Java 8 允许接口包含默认方法静态方法。

接口的特点

  • 一个接口可以被多个类实现;
  • 接口不能实例化,不能创建构造方法;
  • 一个接口可以实现多个接口,一个接口可以继承接口;
  • jdk8.0 之后,接口不仅可以修饰,全局常量,抽象方法,静态方法,默认方法;
  • 接口中的静态方法,只能接口进行调用;
  • 接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

示例:基本使用

//InterfaceTest.java

/**
 * 接口的使用
 * 格式:class A extends B implements C,D{}
 */
public class InterfaceTest {
    public static void main(String[] args) {
        System.out.println(Flyable.MAX_SPEED);
        System.out.println(Flyable.MIN_SPEED);
        // Flyable.MAX_SPEED = 1100; //常量不能被修改
        Plane plane = new Plane();
        plane.fly();
    }
}

interface Flyable {
    // 全局常量
    public static final int MAX_SPEED = 7900;
    // 全局常量 --> 省略不写
    int MIN_SPEED = 7900;

    // Interfaces cannot have constructors
    // public Flyable() {}

    // 抽象方法
    public abstract void fly();

    // 抽象方法 --> 省略不写
    void stop();
}

/**
 * 实现类
 */
class Plane implements Flyable {

    @Override
    public void fly() {
        System.out.println("plane通过引擎飞。。。");
    }

    @Override
    public void stop() {
        System.out.println("plane可以减速停止。。。");
    }
}

/**
 * Kite类实现接口部分方法,声明为abstract
 */
abstract class Kite implements Flyable {

    @Override
    public void fly() {

    }
}

// ******************接口的多继承********************
interface AA {
    void method1();
}

interface BB {
    void method2();
}

interface CC extends AA, BB {

}

注:只有在类中实现接口中所有的的方法,才能完成接口的实现,否者该类必须声明为抽象类(abstract)

示例:同时使用继承和实现接口

在JDK8+版本接口新特性:默认方法+静态方法

父类:SuperClass

//SuperClass.java

public class SuperClass {
    public void method3() {
        System.out.println("SuperClass: method3:中国");
    }
}

接口1:CompareA.java

//CompareA.java

public interface CompareA {
    // 静态方法
    public static void method1() {
        System.out.println("CompareA: method1--北京");
    }

    // 默认方法
    public default void method2() {
        System.out.println("CompareA: method2--上海");
    }

    // 默认方法
    default void method3() {
        System.out.println("CompareA: method3--上海");
    }
}

接口2:CompareB.java

//CompareB.java

public interface CompareB {
    // 默认方法
    default void method3() {
        System.out.println("CompareB: method3--上海");
    }
}

子类(或实现类):SubClassTest.java

//SubClassTest.java

/**
 * 在继承和实现接口的情况下<br>
 * 对象调用方法的顺序:重写的方法 > 父类中的方法 -> 接口中的默认方法
 */
public class SubClassTest {
    public static void main(String[] args) {
        SubClass s = new SubClass();
        // 知识点1:接口中定义静态方法,必须使用接口调用
        // s.method1();
        CompareA.method1();
        // 知识点2:接口的实现类的对象,可以调用接口中的默认方法
        // 如果实现类重写接口中默认的方法,调用时,调用的是重写以后的方法
        s.method2();
        // 知识点3:在子类(或实现类)继承的父类和实现类接口中,声明同名同参的方法
        // 那么子类没有重写此方法的情况下,默认调用的是父类中同名同参的方法 --> 类优先原则
        // 知识点4:如果实现类实现了多个接口,这些接口中声明了同名同参的默认方法
        // 那么在实现类没有重写此方法的情况下,会报错 --> 接口冲突,解决方法:必须在实现类中重写此方法
        s.method3();
        // SubClass.method2(); // 不能直接用子类直接调用默认的方法
        System.out.println("********************");
        s.myMethod();

    }
}

class SubClass extends SuperClass implements CompareA, CompareB {
    // 在实现类中重写接口中的默认方法-->调用的是重写以后的方法
    public void method2() {
        System.out.println("SubClass: mothod2--上海");
    }

    public void method3() {
        System.out.println("SubClass: mothod3--深圳");
    }

    // 调用本类、父类、接口中及接口被重写的方法方式
    public void myMethod() {
        method3(); // 调用子类重写的
        super.method3(); // 调用父类的方法
        // 知识点5:调用接口中的默认方法
        CompareA.super.method3();
        CompareB.super.method3();
    }
}

示例:接口使用中,匿名实现类和匿名对象的使用特点

//USBTest.java

/**
 * 接口:其主要用途就是被实现类实现(面向接口编程)<br>
 * 1、接口的具体使用,体现了多态性<br>
 * 2、接口,实际上可以看做是一种规范,如:USB接口规范<br>
 * 3、匿名实现类、匿名对象的使用特点<br>
 */
public class USBTest {
    public static void main(String[] args) {
        Computer cp = new Computer();
        // 1.创建接口的非匿名实现类的非匿名对象
        Printer usb = new Printer();
        cp.transferData(usb);

        // 2.创建接口的非匿名实现类的匿名对象
        cp.transferData(new Flash());

        // 3.创建接口的匿名实现类的非匿名对象
        USB phone = new USB() {
            @Override
            public void start() {
                System.out.println("手机启动。。。");
            }

            @Override
            public void stop() {
                System.out.println("手机停止。。。");
            }
        };
        cp.transferData(phone);

        // 4.创建接口的匿名实现类的匿名对象
        cp.transferData(new USB() {
            @Override
            public void start() {
                System.out.println("xbox启动。。。");
            }

            @Override
            public void stop() {
                System.out.println("xbox停止。。。");
            }
        });
    }
}

/**
 * 功能类
 */
class Computer {
    public void transferData(USB usb) { // 向上转型,形参为接口对象,实参为该接口的实现类,体现多态的
        usb.start();
        System.out.println("数据传输正在执行。。。");
        usb.stop();
    }

}

/**
 * USB接口
 */
interface USB {
    void start();

    void stop();
}

/**
 * 接口的实现类Flash
 */
class Flash implements USB {

    @Override
    public void start() {
        System.out.println("U盘启动。。。");
    }

    @Override
    public void stop() {
        System.out.println("U盘停止。。。");
    }

}

/**
 * 接口的实现类Printer
 */
class Printer implements USB {

    @Override
    public void start() {
        System.out.println("打印机启动。。。");
    }

    @Override
    public void stop() {
        System.out.println("打印机停止。。。");
    }
}

接口和抽象类对比

抽象类仍然是一个类,在创建新类时只能继承它一个。而创建类的过程中可以实现 多个接口。

实际使用更倾向接口而不是抽象类,在大多数情况,推荐使用普通类。

特性 接口 抽象类
组合 新类可组合多个接口 只能继承单个抽象类
状态 不能包含属性(除了静态属性,不支持对象状态) 可以包含属性,非抽象方法可以引用这些属性
默认方法和抽象方法 不需要在实现类中实现默认方法,默认方法可以其它接口的方法 必须在子类中实现抽象方法
构造器 没有构造器 可以有构造器
可见性 隐式含public 可以使用protected或友好的

异同点:

  • 一个类实现接口的话要实现接口的所以方法,而抽象类不一定;
  • 类可以实现很多个接口,但是只能继承一个抽象类;
  • 接口中声明的变量默认都是final的。抽象类可以包含非final的变量;
  • 接口和抽象类都不可以被实例化;
  • 接口不能创建构造方法,抽象类可以创建构造方法;
  • 接口中的静态方法,只能接口进行调用,而抽象类不是;
  • 实现接口的类必须实现其中的所有方法,继承自抽象类的子类实现所有的抽象方法。

接口的应用

代理模式(Proxy)

定义:为其他对象提供一种代理以控制对该对象的访问。在java开发应用中,代理模式能够在不修改源代码的情况下,增强方法,如在方法前后增加日记记录,权限管理等功能。

应用场景:

  • 安全代理:屏蔽对真实角色的直接访问
  • 远程代理:通过代理类处理远程方法的调用(RMI)
  • Copy-on-Write 代理
  • 保护(Protect or Access)代理
  • Cache 代理
  • 防火墙(Firewall)代理
  • 同步化(Synchronization)代理
  • 智能引用(Smart Reference)代理
  • 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象,比如打开B站先加载文本样式信息,后面图片后才显示,保证流畅打开B站网页

分类:

  • 静态代理:静态定义代理类,就是此代理类针对唯一一个被代理类,即一对一
  • 动态代理:动态生成代理类,代理类并不是在Java代码中实现,而是在运行时期生成,相比静态代理,动态代理可以很方便的对被代理类的方法进行统一处理,如添加方法调用次数、添加日志功能等等,动态代理分为jdk动态代理和cglib动态代理,

NetWork接口、Server和ProxyServer类关系图解:

接口的应用1

示例一:

// NetWorkTest.java

/**
 * 接口的应用:代理模式(Proxy)之静态代理
 */
public class NetWorkTest {
    public static void main(String[] args) {
        Server server = new Server();
        ProxyServer proxyServer = new ProxyServer(server);// ProxyServer类形参:NetWork接口,实参:它的实现类Server对象
        proxyServer.browse(); // 通过代理类调用browse来访问被代理类中真实的browse

    }
}

/**
 * NetWork接口
 */
interface NetWork {
    public void browse();
}

/**
 * 被代理类
 */
class Server implements NetWork {

    @Override
    public void browse() {
        System.out.println("Server服务器访问网络。。。");
    }

}

/**
 * 代理类
 */
class ProxyServer implements NetWork {
    private NetWork netWork;

    public ProxyServer(NetWork netWork) {
        this.netWork = netWork;
    }

    public void check() {
        System.out.println("联网之前进行效验。。。");
    }

    @Override
    public void browse() {
        check();// 在调用之前,添加额外的效验功能
        netWork.browse();
    }

}
//结果:
联网之前进行效验。。。
Server服务器访问网络。。。

示例二:

//StaticProxyTest.java

/**
 * 接口的应用:代理模式
 */
public class StaticProxyTest {
    public static void main(String[] args) {
        Star p = new Proxy(new RealStar());
        p.confer();
        p.signContract();
        p.bookTicket();
        p.sing();
        p.collectMoney();

    }
}

interface Star {
    // 面谈
    void confer();

    // 签合同
    void signContract();

    // 订票
    void bookTicket();

    // 唱歌
    void sing();

    // 收钱
    void collectMoney();
}

/**
 * 被代理类
 */
class RealStar implements Star {

    @Override
    public void confer() {}

    @Override
    public void signContract() {}

    @Override
    public void bookTicket() {}

    @Override
    public void sing() {
        System.out.println("明星,歌唱好运来");
    }

    @Override
    public void collectMoney() {}

}

/**
 * 代理类
 */
class Proxy implements Star {
    private Star star;

    public Proxy(Star realStar) {
        this.star = realStar;
    }

    @Override
    public void confer() {
        System.out.println("经纪人,面谈合作。。。");
    }

    @Override
    public void signContract() {
        System.out.println("经纪人,签合同。。。");
    }

    @Override
    public void bookTicket() {
        System.out.println("经纪人,订机票。。。");
    }

    @Override
    public void sing() {
        star.sing();
    }

    @Override
    public void collectMoney() {
        System.out.println("经纪人,收款。。。");
    }
}
//结果:
经纪人,面谈合作。。。
经纪人,签合同。。。
经纪人,订机票。。。
明星,歌唱好运来
经纪人,收款。。。

工厂模式

实现了创建者和调用者的分离,即将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。设计模式和面向对象设计原则都是为了使得开发项目更加容易拓展和维护,解决方式就是一个"分工"。

工厂模式的分类:

  • 简单工厂模式:也称静态工厂模式,就是工厂类一般是使用静态方法,通过接受不同的参数来返回不同的实例对象
  • 工厂方法模式:不同于简单工厂模式只有一个工厂类(在一个项目或模块中),它有一组实现相同的接口的工厂类
  • 抽象工厂模式:在三个模式中最为抽象、最具一般性,其主要目的给客户端提供一个接口,可以创建多个产品族中的产品对象

注:简单工厂模式可以归并为工厂方法模式

示例:简单工厂模式

//Client02.java

public class Client02 {
    public static void main(String[] args) {
        Car audi = CarFactory.getAudi();
        audi.run();

        Car byd = CarFactory.getBYD();
        byd.run();
    }
}

/**
 * Car接口
 */
interface Car {
    void run();
}

/**
 * Audi实现类
 */
class Audi implements Car {

    @Override
    public void run() {
        System.out.println("Audi is running...");
    }

}

/**
 * BYD实现类
 */
class BYD implements Car {

    @Override
    public void run() {
        System.out.println("BYD is running...");
    }
}

/**
 * CarFactory创建具体Car的工厂类
 */
class CarFactory {

    public static Car getAudi() {
        return new Audi();
    }

    public static Car getBYD() {
        return new BYD();
    }
}
//结果
Audi is running...
BYD is running...

示例:工厂方法模式

//Client03.java

public class Client03 {
    public static void main(String[] args) {
        Car audi = new AudiFactory().getCar();
        audi.run();

        Car byd = new BYDFactory().getCar();
        byd.run();
    }
}

/**
 * Car接口
 */
interface Car {
    void run();
}

/**
 * Audi实现类
 */
class Audi implements Car {

    @Override
    public void run() {
        System.out.println("Audi is running...");
    }

}

/**
 * BYD实现类
 */
class BYD implements Car {

    @Override
    public void run() {
        System.out.println("BYD is running...");
    }
}

/**
 * 工厂接口:创建Car对象的接口
 */
interface Factory {
    Car getCar();
}

/**
 * 工厂接口的实现类
 */
class AudiFactory implements Factory {

    @Override
    public Car getCar() {
        return new Audi();
    }
}

class BYDFactory implements Factory {

    @Override
    public Car getCar() {
        return new BYD();
    }
}
//结果
Audi is running...
BYD is running...
posted @ 2022-10-18 20:55  Bingeone  阅读(45)  评论(0编辑  收藏  举报