• 重新总结 Java 中的接口


    在之前的博客中,我有写到接口,但是还有一些语法没有总结到。本篇博客旨在于将接口拎出来单独总结。

    一、接口

    接口从某种意义上来说,就是完完全全的抽象类。

    接口:由 interface 实现,如:

    interface IA {
    
    }
    
    • 1
    • 2
    • 3

    1. 接口的语法规则

    ① 接口中的普通方法,不能有具体实现,如果非要实现,需要被 default 修饰这个方法

    ② 接口中的所有方法的限定符都是 public,那么所有的方法都可以省略 public,而接口中的所有抽象方法的限定符都是 abstract public,那么所有的抽象方法同样可以省略 abstract public

    ③ 接口中的成员变量默认是被 public static final 修饰的,也就是说,接口中的成员变量必须被初始化

    接口不可以通过 new 实例化对象

    ⑤ 如果一个类实现了一个接口,那么在这个类中,必须重写接口中所有的抽象方法,而且重写的抽象方法必须被 public 修饰(因为接口中的抽象方法默认是 public abstract)

    ⑥ 如果一个类 A 实现了接口 B,那么对应的代码格式为:

    interface IB{
    
    }
    
    class A implements IB{
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ⑦ 一个类可以实现多个接口,然而一个类只能继承一个类

    interface IX{
    
    }
    
    interface IY{
    
    }
    
    class Z{
        
    }
    
    class A extends Z implements IX,IY{
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ⑧ 两个接口之间使用 extends,表示一个接口拓展另一个接口。
    注意下面代码,当类 A 实现了接口 IY ,类 A 必须重写两个方法。

    interface IX{
        void func1();
    }
    
    interface IY extends IX{
        void func2();
    }
    
    class A implements IY{
        @Override
        public void func2() {
    
        }
    
        @Override
        public void func1() {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2. 通过代码来演示接口的语法

    在程序清单1中,我通过注释标明了接口使用时的一些语法规则,这十分重要!

    程序清单1:

    interface IShape{
        public int a; //error
        public static final int b = 10; //right
        int c = 20; //right
        
        public void func1(){ //error
    
        }
        
        default public void func2(){ //right
    
        }
        
        public static void write(){ //right
    
        }
    
        abstract public void draw1(){ //error
    
        }
        
        abstract public void draw2(); //right
        
        void draw3(); //right
    }
    
    public class Test {
        public static void main(String[] args) {
            IShape iShape = new IShape(); //error
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3. 继承与接口的综合

    程序清单2:

    class Animal{
        String name;
        public Animal(String name) {
            this.name = name;
        }
        public void eat(){
            System.out.println(name + " 正在吃东西");
        }
    }
    
    interface IFlying{
        void fly();
    }
    
    class Bird extends Animal implements IFlying{
        public Bird(String name) {
            super(name);
        }
    
    	//重写了接口中的方法
        @Override
        public void fly() {
            System.out.println(name + " 正在飞");
        }
    
    	//重写了父类中的方法
        @Override
        public void eat() {
            System.out.println(name + " 正在喝蜂蜜");
        }
    }
    
    public class Test {
        public static void fly(IFlying iFlying){
            iFlying.fly();
        }
        
        public static void main(String[] args) {
            fly(new Bird("老鹰"));
            new Bird("蜜蜂").eat();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    输出结果:

    out

    对程序清单2 进行分析:

    在程序清单2 中,我们演示了继承和接口,有几个语法点很关键:

    ① 在父类构造带参数的方法的同时,子类也需要构造同样的带参数方法。

    public Bird(String name) {
    
    }
    
    • 1
    • 2
    • 3

    ② 在父类已有的普通成员方法情况下,子类却重写了父类的此方法,那么在编译时,系统直接使用子类重写的方法。

    public void eat(){
    
    }
    
    • 1
    • 2
    • 3

    ③ 接口中的抽象方法是被 abstract public 修饰的,那么在一个类实现接口的时候,我们就必须对此抽象方法进行重写。

    @Override
    public void fly() {
    	System.out.println(name + " 正在飞");
    }
    
    • 1
    • 2
    • 3
    • 4

    二、为什么有些代码 new 了一个接口

    演示1

    通常情况下,一个类实现了另一个接口,我们只能使用 implements 显示地表现出来,如下面的程序:

    程序清单3:

    interface IA{
        void test();
    }
    
    class B implements IA {
        @Override
        public void test() {
            System.out.println("我通过类 B 重写了接口的 test 方法");
        }
    }
    public class Test {
        public static void main(String[] args) {
            B b = new B();
            b.test();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出结果:

    1

    演示2

    而我们知道接口是不能通过 new 来实例化对象的,但有时候我们也会看到【 new 接口 】的情况出现,但不会被编译器报错。因为这是一个匿名内部类实现接口的缘故,只是这个匿名类看起来被隐藏了一样,给人一种 new 了一个接口的错觉,而实际上匿名内部类实现了另一个接口,那么它依然需要重写接口中的抽象方法。所以,一个接口依然不能通过 new 实例化对象!

    //语法格式
    
    new + 接口名 + {
    
    	//这里必须重写接口中的抽象方法!
    	
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    通过下列程序来进行演示为什么可以这么做:

    程序清单4:

    interface IA{
        void test();
    }
    
    public class Test {
        public static void main(String[] args) {
            IA ia = new IA(){ //1
                @Override
                public void test() { //2
                    System.out.println("我匿名重写了接口的 test 方法");
                }
            }; 
    
            ia.test();//3
        }
    }
    
    //注释
    //1. 匿名类实现了接口 IA
    //2. 匿名类重写了 test 方法
    //3. 匿名类调用了 test 方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    输出结果:

    2

    演示3

    程序清单4 又可以简化成程序清单5

    程序清单5:

    interface IA{
        void test();
    }
    
    public class Test1 {
        public static void main(String[] args) {
            new IA(){ //1
                @Override
                public void test() { //2
                    System.out.println("我匿名重写了接口的 test 方法");
                }
            }.test(); //3
        }
    }
    
    //注释
    //1. 匿名类实现了接口 IA
    //2. 匿名类重写了 test 方法
    //3. 匿名类调用了 test 方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    输出结果:

    2

    演示4

    而程序清单5 又可以写成 Lambda 表达式

    ( (IA) () -> { System.out.println("我匿名重写了接口的 test 方法");} ).test();
    
    • 1
  • 相关阅读:
    电子邮件营销初学者指南(二):如何开始与撰写
    Python数据容器的总结
    92、Redis ------- 使用 Lettuce 操作 Redis 的方法和步骤----(文字讲解无代码)
    爱迪转债上市价格预测
    .NET周刊【6月第4期 2024-06-23】
    VoLTE基础自学系列 | IMS的业务触发机制
    在条件神经网络训练中,为什么对于条件特征采取 “don‘t compute derivative w.r.t. inputs”?
    Flutter 知识点
    竞赛 深度学习 opencv python 公式识别(图像识别 机器视觉)
    String字符串,FastJson常用操作方法
  • 原文地址:https://blog.csdn.net/lfm1010123/article/details/125447847