java学习分享之接口

其它的笔记统计在了 JAVA学习记录总贴 中,欢迎大家点评 接口 一个简单例子 public class Interface01 { public static void main(String[] args) { Camera camera = new Camera(); Phone phone ...
java学习分享之接口
java学习分享之接口

其它的笔记统计在了JAVA学习记录总贴 中,欢迎大家点评

接口

一个简单例子

public class Interface01 {
    public static void main(String[] args) {
        Camera camera = new Camera();
        Phone phone = new Phone();
        Computer computer = new Computer();
        computer.work(camera);
        computer.work(phone);
    }
}
public interface UsbInterface {
    public void start();
​
    public void stop();
}
public class Phone implements UsbInterface {
    @Override
    public void start() {
        System.out.println("手机开始工作...");
    }
​
    @Override
    public void stop() {
        System.out.println("手机停止工作...");
    }
}
public class Camera implements UsbInterface {
    @Override
    public void start() {
        System.out.println("相机开始工作...");
    }
​
    @Override
    public void stop() {
        System.out.println("相机停止工作...");
    }
}
public class Computer {
    public void work(UsbInterface usbInterface){
        usbInterface.start();
        usbInterface.stop();
    }
}

基础语法

interface 接口名{
    //属性
    //方法
}
class 类名 implements 接口名{
    自己属性;
    自己方法;
    必须实现的抽象方法;
}

ps:

  1. jdk7.0之前,接口内的所有方法都是抽象方法,即没有方法体。

  2. jdk8.0后,接口可以有静态方法、普通方法,也就是说接口中可以有方法的具体实现,但写方法需要使用default关键字

public interface AInterface {
    public int n1 = 10;
    public void hi();
​
    // 普通方法要写default关键字
    public default void ok(){
        System.out.println("ok()方法被调用");
    }
​
    public static void cry(){
        System.out.println("cry()方法被调用");
    }
}

接口应用场景

我们思考一个场景:假设一位产品经理和三位程序员一起工作,需要编写三个类,分别实现对 MySQL、Oracle、DB2 数据库的连接与关闭操作。

如果不使用接口,三位程序员很可能会按照各自的标准来写,结果开发出三个方法命名各异、实现方式也不同的类。产品经理拿到这些类后,甚至可能发现连方法名都无法统一,自然也难以进行统一调用。

但如果产品经理提前设计好接口,在接口中定义好需要被实现的方法,三位程序员只需按照这个接口去开发即可。这样最终得到的类不仅方法命名统一,而且因为它们都实现了同一个接口,产品经理还可以利用多态特性,轻松实现统一调用。

因此接口的好处是

  • 规范统一

  • 多台调用

public class Interface2 {
    public static void main(String[] args) {
        Interface2.useDatabase(new MySql());
        Interface2.useDatabase(new Oracle());
        Interface2.useDatabase(new DB2());
    }
​
    public static void useDatabase(DateBase dateBase){
        dateBase.connect();
        dateBase.close();
    }
}
​
interface DateBase {
    public void connect();
​
    public void close();
}
​
class MySql implements DateBase {
​
    @Override
    public void connect() {
        System.out.println("连接MySql数据库");
    }
​
    @Override
    public void close() {
        System.out.println("关闭MySql数据库");
    }
}
​
class Oracle implements DateBase {
​
    @Override
    public void connect() {
        System.out.println("连接Oracle数据库");
    }
​
    @Override
    public void close() {
        System.out.println("关闭Oracle数据库");
    }
}
​
class DB2 implements DateBase {
    @Override
    public void connect() {
        System.out.println("连接DB2数据库");
    }
​
    @Override
    public void close() {
        System.out.println("关闭DB2数据库");
    }
}

接口使用细节

  1. 接口本身是不能实例化的。

  2. 接口中写抽象方法可以省略abstract关键字,接口中的所有方法默认是public

  3. 一个普通类实现接口,就必须将该接口的所有方法都实现

  4. 抽象类实现接口,可以不用实现接口的方法

  5. 一个类可以同时实现多个接口

  6. 接口中的属性默认且只能是public static final的,比如int a = 1; 其实就是 public static final int a = 1;(你可以修改一下值,就能证明是fianl的;写private int a = 1;会报错,也能证明它是public的)

  7. 接口中属性的访问方式:接口名.属性名(因为本质是静态的嘛)

  8. 一个接口不能继承其他的类,但是可以继承别的多个接口,比如

    interface A extends B, C{}
    

    接口之间的关系是继承,接口和类之间的关系是实现

  9. 接口的修饰符合类一样,只能是默认或者public

小练习

interface A{
    int a = 23;
}
​
// 实现接口的类
class B implements A{
}
​
// main方法所在的测试类(补充完整可运行结构)
public class Test {
    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.a);
        System.out.println(A.a);
        System.out.println(B.a);
    }
}

请判断上述代码语法是否可以通过

答案如下

全都可以通过。
int a=23相当于public static final int a=23,没问题
A里面没有抽象方法,所以B不需要实现
三种a的调用方法,由于a本身是静态的,因此无论是用A(接口)B(实现接口的类)b(实现接口的类的对象),都可以完成调用,不过第三种形式不推荐。

接口 VS 继承

java中的实现机制,可以看作是对继承机制的一种补充。

  • 接口和继承解决的问题不同

    • 继承价值在于:解决代码的复用性和可维护性

    • 接口价值在于:设计好各种规范方法,让其他类去实现

  • 接口比继承更加灵活

    • 继承是 is-a的关系

    • 接口是 can do的关系

  • 接口在一定程度上实现了代码解耦【依赖于接口规范性+动态绑定机制】

// 继承:is-a 关系
class Animal {}
class Dog extends Animal {}  // Dog is an Animal
​
// 接口:can do 关系
interface Swimmable {
    void swim();
}
interface Flyable {
    void fly();
}
​
// 一个类可以同时具备多种能力
class Duck extends Animal implements Swimmable, Flyable {
    @Override
    public void swim() { System.out.println("鸭子游泳"); }
    @Override
    public void fly() { System.out.println("鸭子飞"); }
}

接口的多态特性

是的,接口也可以实现多态,代码示例如下:

public class Interface2 {
    public static void main(String[] args) {
        useDatabase(new MySql());
        useDatabase(new Oracle());
        useDatabase(new DB2());
    }
    static void useDatabase(DateBase dateBase){
        dateBase.connect();
        dateBase.close();
    }
}
​
interface DateBase {
    public void connect();
​
    public void close();
}
​
class MySql implements DateBase {
    @Override
    public void connect() {
        System.out.println("连接MySql数据库");
    }
​
    @Override
    public void close() {
        System.out.println("关闭MySql数据库");
    }
}
​
class Oracle implements DateBase {
​
    @Override
    public void connect() {
        System.out.println("连接Oracle数据库");
    }
​
    @Override
    public void close() {
        System.out.println("关闭Oracle数据库");
    }
}
​
class DB2 implements DateBase {
    @Override
    public void connect() {
        System.out.println("连接DB2数据库");
    }
​
    @Override
    public void close() {
        System.out.println("关闭DB2数据库");
    }
}

可以看到useDatabase(DateBase dateBase)接收一个DataBase接口类型的参数,但是实际上可以传入实现该接口的类的实例,并且根据每个类不同的实现来调用

此外,还可以这么做

DateBase db = new DB2(); //接口的向上转型
DB2 db1 = (DB2)db; //接口的向下转型

当然也可以写接口数组,来实现多态特性

DateBase[] databases = new DateBase[3];
databases[0] = new MySql();
databases[1] = new Oracle();
databases[2] = new DB2();
for (DateBase database : databases) {
    database.connect();
    database.close();
}

此外,接口的多态特性也是可以传递的,如下代码

public class Interface3 {
    public static void main(String[] args) {
        IH ih = new T();
        IG ig = new T();
    }
}
​
interface IG{}
interface IH extends IG{}
class T implements IH{}

小练习2

下面这段代码是否有错,如果有该如何修改呢?

interface A{
    int x = 0;
}
class B{
    int x = 1;
}
class C extends B implements A {
    public void pX(){
        System.out.println(x);
    }
    public static void main(String[] args) {
        new C().pX();
    }
}

答案:

有错,类C同时继承了B的x和接口A的x,无法确定x是哪个,修改方法是
if你想访问接口的x then A.x
if你想访问父类B的x then super.x

2 个帖子 - 2 位参与者

阅读完整话题

来源: LinuxDo 最新话题查看原文