• 重新总结 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
  • 相关阅读:
    【音视频基础】AVI文件格式
    MySQL常用函数集锦 --- 字符串|数值|日期|流程函数总结
    中国传统美食网页HTML代码 学生网页课程设计期末作业下载 美食大学生网页设计制作成品下载 DW餐饮美食网页作业代码下载
    vue项目中,把已经写好的html直接放进去,而不经过编译,直接跳转html页面
    操作系统的运行机制
    HCIP实验6
    java计算机毕业设计ssm宁夏源沣医药线上销售平台thd3v(附源码、数据库)
    ROS 导航
    猿创征文|我的半年算法学习成长之路~
    MAC中文版 FCPX V10.6.6 专属视频剪辑后期工具安装教程
  • 原文地址:https://blog.csdn.net/lfm1010123/article/details/125447847