interface_interfaces - CSDN
interface 订阅
interface是面向对象编程语言中接口操作的关键字,功能是把所需成员组合起来,用来装封一定功能的集合。它好比一个模板,在其中定义了对象必须实现的成员,通过类或结构来实现它。接口不能直接实例化,即ICount ic=new iCount()是错的。接口不能包含成员的任何代码,只定义成员本身。接口成员的具体代码由实现接口的类提供。接口使用interface关键字进行声明。 展开全文
interface是面向对象编程语言中接口操作的关键字,功能是把所需成员组合起来,用来装封一定功能的集合。它好比一个模板,在其中定义了对象必须实现的成员,通过类或结构来实现它。接口不能直接实例化,即ICount ic=new iCount()是错的。接口不能包含成员的任何代码,只定义成员本身。接口成员的具体代码由实现接口的类提供。接口使用interface关键字进行声明。
信息
面    向
对象编程语言中接口操作
外文名
interface
类    型
关键字
注意点2
接口不能包含成员的任何代码
中文名
接口
功    能
把所需成员组合起来
注意点1
接口不能直接实例化
interface关键字
接口是一种约束形式,其中只包括成员定义,不包含成员实现的内容。声明格式如下:[attributes] [modifiers] interface identifier [: base-list] {interface-body} {;}1、attributes(可选):附加的定义性信息。2、modifiers(可选): 允许使用的修饰符有 new 和四个访问修饰符。分别是:new、public、protected、internal、 private。在一个接口定义中同一修饰符不允许出现多次,new 修饰符只能出现 在嵌套接口中,表示覆盖了继承而来的同名成员。The public, protected, internal, and private 修饰符定义了对接口的访问权限。3、指示器和事件。4、identifier:接口名称。5、base-list(可选):包含一个或多个显式基接口的列表,接口间由逗号分隔。6、interface-body:对接口成员的定义。7、接口可以是命名空间或类的成员,并且可以包含下列成员的签名: 方法、属性、索引器 。8、一个接口可从一个或多个基接口继承。接口这个概念在C#和Java中非常相似。接口的关键词是interface,一个接口可以扩展一个或者多个其他接口。按照惯例,接口的名字以大写字母"I"开头。
收起全文
精华内容
参与话题
  • Java 接口(interface)的用途和好处

    万次阅读 多人点赞 2014-11-16 23:52:34
    首先不懂什么是interface的可以参考这里 http://blog.csdn.net/nvd11/article/details/18888415 不过上面的bo
    http://write.blog.csdn.net/postedit/41129935
    

    首先不懂什么是interface的可以参考这里

    http://blog.csdn.net/nvd11/article/details/18888415



    不过上面的博文只是简单介绍了interface的语法和用法.  对Interface的用途并没有介绍清楚. 本文就是1个补充.


    一. 对接口的三个疑问

    很多初学者都大概清楚interface是1个什么, 我们可以定义1个接口, 然后在里面定义一两个常量(static final) 或抽象方法.

    然后以后写的类就可以实现这个接口, 重写里面的抽象方法. 

    很多人说接口通常跟多态性一起存在.

    接口的用法跟抽象类有点类似.


    但是为何要这么做呢.

    1.为什么不直接在类里面写对应的方法,  而要多写1个接口(或抽象类)?

    2.既然接口跟抽象类差不多, 什么情况下要用接口而不是抽象类.

    3. 为什么interface叫做接口呢? 跟一般范畴的接口例如usb接口, 显卡接口有什么联系呢?

    二. 接口引用可以指向实现该接口的对象

    我们清楚接口是不可以被实例化, 但是接口引用可以指向1个实现该接口的对象.

    也就是说.

    假如类A impletments 了接口B

    那么下面是合法的:

    B b = new A();


    也可以把A的对象强制转换为 接口B的对象

    A a = new A90;
    B b = (B)a;

    这个特性是下面内容的前提.


    三. 抽象类为了多态的实现.

    第1个答案十分简单, 就是为了实现多态.

    下面用详细代码举1个例子.


    先定义几个类,

    动物(Animal) 抽象类

    爬行动物(Reptile) 抽象类  继承动物类

    哺乳动物(Mammal) 抽象类 继承动物类

    山羊(Goat) 继承哺乳动物类

    老虎(Tiger)  继承哺乳动物类

    兔子(Rabbit) 继承哺乳动物类

    蛇(Snake)   继承爬行动物类


    农夫(Farmer)   没有继承任何类 但是农夫可以给Animal喂水(依赖关系)


    它们的关系如下图:



    3.1 Animal类

    这个是抽象类, 显示也没有"动物" 这种实体

    类里面包含3个抽象方法.

    1. 静态方法getName()

    2. 移动方法move(), 因为动物都能移动.  但是各种动物有不同的移动方法, 例如老虎和山羊会跑着移动, 兔子跳着移动, 蛇会爬着移动.

    作为抽象基类, 我们不关心继承的实体类是如何移动的, 所以移动方法move()是1个抽象方法.  这个就是多态的思想.


    3. 喝水方法drink(), 同样, 各种动物有各种饮水方法. 这个也是抽象方法.

    代码:

    abstract class Animal{
        public abstract String getName();
        public abstract void move(String destination);
        public abstract void drink();
    }


    3.2 Mammal类

    这个是继承动物类的哺乳动物类, 后面的老虎山羊等都继承自这个类.

    Mammal类自然继承了Animal类的3个抽象方法, 实体类不再用写其他代码.

    abstract class Mammal extends Animal{
    
    }
    
    

    3.3 Reptile类

    这个是代表爬行动物的抽象类, 同上, 都是继承自Animal类.

    abstract class Reptile extends Animal{
    
    }


    3.4 Tiger类

    老虎类就是1个实体类, 所以它必须重写所有继承自超类的抽象方法, 至于那些方法如何重写, 则取决于老虎类本身.

    class Tiger extends Mammal{
        private static String name = "Tiger";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Goat moved to " + destination + ".");
        }
    
        public void drink(){
            System.out.println("Goat lower it's head and drink.");
        }
    }
    
    

    如上, 老虎的移动方法很普通, 低头喝水.


    3.5 Goat类 和 Rabbit类

    这个两个类与Tiger类似, 它们都继承自Mammal这个类.

    class Goat extends Mammal{
        private static String name = "Goat";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Goat moved to " + destination + ".");
        }
    
        public void drink(){
            System.out.println("Goat lower it's head and drink.");
        }
    }
    

    兔子: 喝水方法有点区别

    class Rabbit extends Mammal{
        private static String name = "Rabbit";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Rabbit moved to " + destination + ".");
        }
    
        public void drink(){
            System.out.println("Rabbit put out it's tongue and drink.");
        }
    }

    3.6 Snake类

    蛇类继承自Reptile(爬行动物)

    移动方法和喝水方法都跟其他3动物有点区别.

    class Snake extends Reptile{
        private static String name = "Snake";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Snake crawled to " + destination + ".");
        } 
    
        public void drink(){
            System.out.println("Snake dived into water and drink.");
        }
    }

    3.7 Farmer 类

    Farmer类不属于 Animal类族, 但是Farmer农夫可以给各种动物, 喂水.


    Farmer类有2个关键方法, 分别是

    bringWater(String destination)    -> 把水带到某个地点


    另1个就是feedWater了, 

    feedWater这个方法分为三步:

    首先是农夫带水到饲养室,(bringWater())

    接着被喂水动物走到饲养室,(move())

    接着动物喝水(drink())


    Farmer可以给老虎喂水, 可以给山羊喂水, 还可以给蛇喂水, 那么feedWater()里的参数类型到底是老虎,山羊还是蛇呢.


    实际上因为老虎,山羊, 蛇都继承自Animal这个类, 所以feedWater里的参数类型设为Animal就可以了.

    Farmer类首先叼用bringWater("饲养室"),

    至于这个动物是如何走到饲养室和如何喝水的, Farmer类则不用关心.

    因为执行时, Animal超类会根据引用指向的对象类型不同 而 指向不同的被重写的方法.  这个就是多态的意义.




    代码如下:

    class Farmer{
        public void bringWater(String destination){
            System.out.println("Farmer bring water to " + destination + ".");
        }
    
        public void feedWater(Animal a){ // polymorphism
            this.bringWater("Feeding Room");
            a.move("Feeding Room");
            a.drink();
        }
    
    }


    3.7 执行农夫喂水的代码.

    下面的代码是1个农夫依次喂水给一只老虎, 一只羊, 以及一条蛇

     public static void f(){
            Farmer fm = new Farmer();
            Snake sn = new Snake();
            Goat gt = new Goat();
            Tiger tg = new Tiger();
    
            fm.feedWater(sn);
            fm.feedWater(gt);
            fm.feedWater(tg);
        }
    

    农夫只负责带水过去制定地点, 而不必关心老虎, 蛇, 山羊它们是如何过来的. 它们如何喝水. 这些农夫都不必关心.

    只需要调用同1个方法feedWater.  


    执行结果:

       [java] Farmer bring water to Feeding Room.
         [java] Snake crawled to Feeding Room.
         [java] Snake dived into water and drink.
         [java] Farmer bring water to Feeding Room.
         [java] Goat moved to Feeding Room.
         [java] Goat lower it's head and drink.
         [java] Farmer bring water to Feeding Room.
         [java] Goat moved to Feeding Room.
         [java] Goat lower it's head and drink.
    
    


    不使用多态的后果?:

    而如果老虎, 蛇, 山羊的drink() 方法不是重写自同1个抽象方法的话, 多态就不能实现.

    农夫类就可能要根据参数类型的不同而重载很多个  feedWater()方法了.

    而且每增加1个类(例如 狮子Lion)

    就需要在农夫类里增加1个feedWater的重载方法 feedWater(Lion l)...


    而接口跟抽象类类似,

    这个就回答了不本文第一个问题.

    1.为什么不直接在类里面写对应的方法,  而要多写1个接口(或抽象类)?



    四. 抽象类解决不了的问题.

    既然抽象类很好地实现了多态性, 那么什么情况下用接口会更加好呢?


    对于上面的例子, 我们加一点需求.


    Farmer 农夫多了1个技能, 就是给另1个动物喂兔子(囧).

    BringAnimal(Animal a, String destination)     把兔子带到某个地点...

    feedAnimal(Animal ht, Animal a)            把动物a丢给动物ht


    注意农夫并没有把兔子宰了, 而是把小动物(a)丢给另1个被喂食的动物(ht).

    那么问题来了, 那个动物必须有捕猎这个技能.  也就是我们要给被喂食的动物加上1个方法(捕猎) hunt(Animal a).


    但是现实上不是所有动物都有捕猎这个技能的, 所以我们不应该把hunt(Animal a)方法加在Goat类和Rabbit类里,  只加在Tiger类和Snake类里.


    而且老虎跟蛇的捕猎方法也不一样, 则表明hunt()的方法体在Tiger类里和Snake类里是不一样的.


    下面有3个方案.

    1. 分别在Tiger类里和Snake类里加上Hunt() 方法.  其它类(例如Goat) 不加.

    2. 在基类Animal里加上Hunt()抽象方法. 在Tiger里和Snake里重写这个Hunt() 方法.

    3. 添加肉食性动物这个抽象类.   


    先来说第1种方案.

    这种情况下, Tiger里的Hunt(Animal a)方法与 Snake里的Hunt(Animal a)方法毫无关联. 也就是说不能利用多态性.

    导致Farm类里的feedAnimal()方法需要分别为Tiger 与 Snake类重载. 否决.


    第2种方案:

    如果在抽象类Animal里加上Hunt()方法, 则所有它的非抽象派生类都要重写实现这个方法, 包括 Goat类和 Rabbit类.

    这是不合理的, 因为Goat类根本没必要用到Hunt()方法, 造成了资源(内存)浪费.


    第3种方案:

    加入我们在哺乳类动物下做个分叉, 加上肉食性哺乳类动物, 非肉食性哺乳动物这两个抽象类?


    首先,

    肉食性这种分叉并不准确, 例如很多腐蚀性动物不会捕猎, 但是它们是肉食性.

    其次

    这种方案会另类族图越来越复杂, 假如以后再需要辨别能否飞的动物呢, 增加飞翔 fly()这个方法呢? 是不是还要分叉?

    再次,

    很现实的问题, 在项目中, 你很可能没机会修改上层的类代码, 因为它们是用Jar包发布的, 或者你没有修改权限.


    这种情况下就需要用到接口了.


    五.接口与多态 以及 多继承性.

    上面的问题, 抽象类解决不了, 根本问题是Java的类不能多继承.

    因为Tiger类继承了动物Animal类的特性(例如 move() 和 drink()) , 但是严格上来将 捕猎(hunt())并不算是动物的特性之一. 有些植物, 单细胞生物也会捕猎的.


    所以Tiger要从别的地方来继承Hunt()这个方法.  接口就发挥作用了.


    修改后的UML图如下:



    5.1 Huntable接口

    由UML图可知,

    我们增加了1个Huntable接口.

    接口里有1个方法hunt(Animal a), 就是捕捉动物, 至于怎样捕捉则由实现接口的类自己决定.


    代码:

    interface Huntable{
        public void hunt(Animal a);
    }



    5.2 Tiger 类

    既然定义了1个Huntable(可以捕猎的)接口.

    Tiger类就要实现这个接口并重写接口里hunt()方法.

    class Tiger extends Mammal implements Huntable{
        private static String name = "Tiger";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Goat moved to " + destination + ".");
        }
    
        public void drink(){
            System.out.println("Goat lower it's head and drink.");
        }
    
        public void hunt(Animal a){
            System.out.println("Tiger catched " + a.getName() + " and eated it");
        }
    
    }

    5.3 Snake类

    同样:

    class Snake extends Reptile implements Huntable{
        private static String name = "Snake";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Snake crawled to " + destination + ".");
        } 
    
        public void drink(){
            System.out.println("Snake dived into water and drink.");
        }
    
        public void hunt(Animal a){
            System.out.println("Snake coiled " + a.getName() + " and eated it");
        }
    }

    可见同样实现接口的hunt()方法, 但是蛇与老虎的捕猎方法是有区别的.


    5.4 Farmer类

    这样的话. Farmer类里的feedAnimal(Animal ht, Animal a)就可以实现多态了.

    class Farmer{
        public void bringWater(String destination){
            System.out.println("Farmer bring water to " + destination + ".");
        }
        
        public void bringAnimal(Animal a,String destination){
            System.out.println("Farmer bring " + a.getName() + " to " + destination + ".");
        }
    
        public void feedWater(Animal a){
            this.bringWater("Feeding Room");
            a.move("Feeding Room");
            a.drink();
        }
    
        public void feedAnimal(Animal ht , Animal a){
            this.bringAnimal(a,"Feeding Room");
            ht.move("Feeding Room");
            Huntable hab = (Huntable)ht;
            hab.hunt(a);
        }
    
    }

    关键是这一句
    Huntable hab = (Huntable)ht;
    本文一开始讲过了, 接口的引用可以指向实现该接口的对象.

    当然, 如果把Goat对象传入Farmer的feedAnimal()里就会有异常, 因为Goat类没有实现该接口. 上面那个代码执行失败.


    如果要避免上面的问题.

    可以修改feedAnimal方法:

        public void feedAnimal(Huntable hab, Animal a){
            this.bringAnimal(a,"Feeding Room");
            Animal ht = (Animal)hab;
            ht.move("Feeding Room");
            hab.hunt(a);
        }

    这样的话, 传入的对象就必须是实现了Huntable的对象, 如果把Goat放入就回编译报错.

    但是里面一样有一句强制转换

    Animal ht = (Animal)hab
    反而更加不安全, 因为实现的Huntable的接口的类不一定都是Animal的派生类.

    相反, 接口的出现就是鼓励多种不同的类实现同样的功能(方法)


    例如,假如一个机械类也可以实现这个接口, 那么那个机械就可以帮忙打猎了(囧)

    1个植物类(例如捕蝇草),实现这个接口, 也可以捕猎苍蝇了.


    也就是说, 接口不会限制实现接口的类的类型.


    执行输出:

         [java] Farmer bring Rabbit to Feeding Room.
         [java] Snake crawled to Feeding Room.
         [java] Snake coiled Rabbit and eated it
         [java] Farmer bring Rabbit to Feeding Room.
         [java] Goat moved to Feeding Room.
         [java] Tiger catched Rabbit and eated it
    



    这样, Tiger类与Snake类不但继承了Animal的方法, 还继承(实现)了接口Huntable的方法, 一定程度上弥补java的class不支持多继承的特点.

    六.接口上应用泛型.

    上面的Huntable里还是有点限制的,

    就是它里面的hunt()方法的参数是 Animal a, 也就是说这个这个接口只能用于捕猎动物.


    但是在java的世界里, 接口里的方法(行为)大多数是与类的类型无关的.

    也就是说, Huntable接口里的hunt()方法里不单只可以捕猎动物, 还可以捕猎其他东西(例如 捕猎植物... 敌方机械等)


    6.1 Huntable接口

    首先要在Huntable接口上添加泛型标志:<T>

    interface Huntable<T>{
        public void hunt(T o);
    }
    
    

    然后里面的hunt()的参数的类型就写成T, 表示hunt()方法可以接受多种参数, 取决于实现接口的类.


    6.2 Tiger类(和Snake类)

    同样, 定义tiger类时必须加上接口的泛型标志<Animal>, 表示要把接口应用在Animal这种类型.

    class Tiger extends Mammal implements Huntable<Animal>{
        private static String name = "Tiger";
        public String getName(){
            return this.name;
        }
    
        public void move(String destination){
            System.out.println("Goat moved to " + destination + ".");
        }
    
        public void drink(){
            System.out.println("Goat lower it's head and drink.");
        }
    
        public void hunt(Animal a){
            System.out.println("Tiger catched " + a.getName() + " and eated it");
        }
    
    }

    这样, 在里面hunt()参数就可以指明类型Animal了,  表示老虎虽然有捕猎这个行为, 但是只能捕猎动物.



    七.什么情况下应该使用接口而不用抽象类.

    好了, 回到本文最重要的一个问题.


    做个总结

    1. 需要实现多态

    2. 要实现的方法(功能)不是当前类族的必要(属性).

    3. 要为不同类族的多个类实现同样的方法(功能).



    下面是分析:

    7.1 需要实现多态

    很明显, 接口其中一个存在意义就是为了实现多态. 这里不多说了.

    而抽象类(继承) 也可以实现多态



    7.2. 要实现的方法(功能)不是当前类族的必要(属性).

    上面的例子就表明, 捕猎这个方法不是动物这个类必须的,

    在动物的派生类中, 有些类需要, 有些不需要.  


    如果把捕猎方法卸载动物超类里面是不合理的浪费资源.


    所以把捕猎这个方法封装成1个接口, 让派生类自己去选择实现!


    7.3. 要为不同类族的多个类实现同样的方法(功能).

    上面说过了, 其实不是只有Animal类的派生类才可以实现Huntable接口.

    如果Farmer实现了这个接口, 那么农夫自己就可以去捕猎动物了...


    我们拿另个常用的接口Comparable来做例子.


    这个接口是应用了泛型,

    首先, 比较(CompareTo) 这种行为很难界定适用的类族, 实际上, 几乎所有的类都可以比较.

    比如 数字类可以比较大小,   人类可以比较财富,  动物可以比较体重等.


    所以各种类都可以实现这个比较接口.

    一旦实现了这个比较接口. 就可以开启另1个隐藏技能:


    就是可以利用Arrays.sort()来进行排序了.


    就如实现了捕猎的动物,

    可以被农夫Farmer喂兔子一样...



    八.接口为什么会被叫做接口, 跟真正的接口例如usb接口有联系吗?


    对啊, 为什么叫接口, 而不叫插件(plugin)呢,  貌似java接口的功能更类似1个插件啊.

    插上某个插件, 就有某个功能啊.


    实际上, 插件与接口是相辅相成的.


    例如有1个外部存储插件(U盘), 也需要使用设备具有usb接口才能使用啊.


    再举个具体的例子.

    个人电脑是由大型机发展而来的


    大型机->小型机->微机(PC)


    而笔记本是继承自微机的.


    那么问题来了.


    对于, 计算机的CPU/内存/主板/独显/光驱/打印机 有很多功能(方法/行为), 那么到底哪些东西是继承, 哪些东西是接口呢.


    首先,  cpu/内存/主板 是从大型机开始都必备的, 任何计算机都不能把它们去掉.

    所以, 这三样东西是继承的, 也就说笔记本的cpu/内存/主板是继承自微机(PC)的


    但是/光驱/呢,    现实上很多超薄笔记本不需要光驱的功能.

    如果光驱做成继承, 那么笔记本就必须具有光驱, 然后屏蔽光驱功能, 那么这台笔记本还能做到超薄吗? 浪费了资源.


    所以光驱,打印机这些东西就应该做成插件.


    然后, 在笔记本上做1个可以插光驱和打印机的接口(usb接口).

    也就是说, PC的派生类, 有些(笔记本)可以不实现这个接口, 有些(台式机)可以实现这个接口,只需要把光驱插到这个接口上.


    至于光驱是如何实现的,

    例如一些pc派生类选择实现蓝光光驱, 有些选择刻录机.  但是usb接口本身并不关心. 取决与实现接口的类.

    这个就是现实意义上的多态性啊.











































































    展开全文
  • 接口(interface)基本定义

    万次阅读 2018-08-16 00:42:08
    但在接口(interface)中,所有的方法必须都是抽象的,不能有方法体,它比抽象类更加“抽象”。 接口(interface)是我们开发java项目,必须用到的方法,而接口是一种完全抽象的设计,没有任何实现。 接口(interface)...

    在抽象类中,可以包含一个或多个抽象方法;但在接口(interface)中,所有的方法必须都是抽象的,不能有方法体,它比抽象类更加“抽象”。

    接口(interface)是我们开发java项目,必须用到的方法,而接口是一种完全抽象的设计,没有任何实现。

    接口(interface)的特征:

    1.所有的成员变量都是public、static、final类型。
    2.所有的方法都是public、abstract类型。
    3.所有的嵌套类型(类或接口)都是public、static类型。

    由此可知,接口中的所有成员都是public的,因为接口是抽象的,必须由其他类所实现,故成员一定要具备足够的访问权限。

    如果声明一个接口,并且在接口中没有显式声明任何成员,那个这个接口为空吗?在这个问题之前,先看一个简单的实例。
    例:

    package deep;

    public class UpCast implements Graph {
    @Override
    public void draw() { }

    public void cast() { }

    public static void main(String[] args) {
    UpCast u = new UpCast();
    u.draw();
    u.cast();
    Graph g = u;
    g.draw();
    // g.cast(); 不能调用cast方法
    }
    }

    interface Graph {
    void draw();
    }

    当类上转为接口时,只能调用接口中声明的方法,而不能够调用自己类中声明的方法。根据这个例子可以说明,通过接口类型的引用,所能调用的方法应该是在接口中声明的,否则无法调用。

    于是,我们来测试下没有声明任何成员的接口,看看其是否为空。

    例:

    package deep;

    public class EmptyInterfaceTest implements EmptyInterface {

    public static void main(String[] args) throws InterruptedException {
    EmptyInterface e = new EmptyInterfaceTest();
    e.equals(null);
    e.getClass();
    e.hashCode();
    e.notify();
    e.notifyAll();
    e.toString();
    e.wait();
    e.wait(100L);
    e.wait(100L, 100);
    }
    }

    interface EmptyInterface {
    }

    这个程序可以通过编译。也许大家会感觉很奇怪,在EmptyInterface接口中没有声明任何成员,为什么通过接口引用(e)还可以调用这一系列方法呢?这是因为,接口从来都不是空的,即使我们没有显式声明任何方法,在接口中也默认存在9个方法,这9个方法与Object类中声明的9个public方法相对应。这也说明,即使没有显式声明任何成员的“空接口”,事实上也并非为空,因为至少存在9个方法成员.

    接口不能实例化

    接口是一种完全抽象的设计,不能实例化,即我们不能创建接口类型的对象,因为这样的对象没有任何实现,是毫无意义的。可是,下面的程序怎么来解释呢?

    例:
    package deep;

    public class Instantiated {
    public static void main(String[] args) {
    Bird b = new Bird() {
    @Override
    public void fly() {
    System.out.println(“flying”);
    }
    };
    b.fly();
    }
    }

    interface Bird {
    void fly();
    }

    虽然不能像创建对象那样使用new来实例化接口,也似乎使用new Bird来创建了接口的实例,并且实现了fly方法。该程序可以通过编译,运行结果如下:
    flying

    一切都运转正常,这是否说是接口也可以实例化呢?
    其实,这一切都是假象而已。接口是完全抽象的设计,不可以实例化。细心的读者也会发现,在编译Instantiated.java后,会生成3个class文件,分别为Instantiated.class、Bird.class、Instantiated$1.class,前两个并不奇怪,关键是第3个class文件从何而来呢?
    程序中的创建方式,是使用匿名类来实现的,第3个class文件也就是从这里产生的。其实,程序中的new Bird并没有真正的创建一个Bird类型的“接口对象”,而是创建了一个匿名类。该类实现了Bird接口,并且实现了Bird接口中的fly方法。

    口的继承

    在Java中,类不允许多重继承,因为从多个类继承的成员及其容易造成混淆与错用,Java中去除了这一特性。不过,对于接口来说,因为其设计是完全抽象的,不包含任何实现,因而接口的继承与类的继承相比,问题相对较少,故Java中接口是可以多重继承的。
    接口中的方法都是abstract类型的,目的是要求实现接口的类去实现这些抽象方法,并通过接口引用来指向实现接口的对象,这样就可以调用接口中的方法。故接口中都是实例方法,不允许声明static(静态)方法。因为静态方法是不依赖对象而存在的,可以通过类名直接调用,也不需要创建对象。
    如果子接口声明了与父接口中相同名称的变量,就会隐藏父类接口中的同名变量。
    如果两个接口中声明了相同名称的变量,当一个类实现了这两个接口,或者子接口多重继承这两个接口,则对该同名变量访问的时候,必须使用限定名称,使用简单名称就会引发编译错误。

    例:

    package deep;

    interface Donkey {
    String kind = “donkey”;
    }

    interface Horse {
    String kind = “horse”;
    }

    interface Mule extends Donkey, Horse {
    // String des = kind; The field kind is ambiguous
    String des2 = Donkey.kind;
    String des3 = Horse.kind;
    }

    class MuleClass implements Mule {
    // String des = kind; The field kind is ambiguous
    String des2 = Donkey.kind;
    String des3 = Horse.kind;
    }

    class MuleClass2 implements Donkey, Horse {
    // String des = kind; The field kind is ambiguous
    String des2 = Donkey.kind;
    String des3 = Horse.kind;
    }

    接口作为类型使用

    接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法,Java 运行时系统会动态地确定应该使用哪个类中的方法,实际上是调用相应的实现类的方法。

    展开全文
  • interface 是什么类型?

    2019-06-17 15:52:34
    interface不是类型,interface是关键字,定义为 interface 是什么类型,是由其“变量”决定的。如果一定要强去理解“接口到底是什么类型”?那么它必然是引用类型(这句话与前面那句矛盾)。 class也不是类型,只...

    interface不是类型,interface是关键字,定义为 interface 是什么类型,是由其“变量”决定的。如果一定要强去理解“接口到底是什么类型”?那么它必然是引用类型(这句话与前面那句矛盾)。

    class也不是类型,只不过定义为 class 都是引用类型。

    看看实例吧:

        public interface ITest
        {
             string Text { get; set; }
        }
        
        public struct TestStruct : ITest
        {
            public string Text { get; set; }
        }
        
        public class TestClass : ITest
        {
            public string Text { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Test1:");
                Test1();
                Console.WriteLine("Test2:");
                Test2();
                Console.ReadKey();
            }
    
            static void Test1()
            {
                TestStruct t1 = new TestStruct();
                t1.Text = "我爱辣妹";
                Func(t1);
                Console.WriteLine(t1.Text);
                TestClass t2 = new TestClass();
                t2.Text = "我爱辣妹";
                Func(t2);
                Console.WriteLine(t2.Text);
            }
    
            static void Test2()
            {
                ITest t1 = new TestStruct();
                t1.Text = "我爱辣妹";
                Func(t1);
                Console.WriteLine(t1.Text);
                ITest t2 = new TestClass();
                t2.Text = "我爱辣妹";
                Func(t2);
                Console.WriteLine(t2.Text);
            }
    
            static void Func(ITest test)
            {
                test.Text = "辣妹爱我";
            }
        }
    

     

    转载于:https://www.cnblogs.com/sofire/archive/2010/12/07/1898658.html

    展开全文
  • java中接口(interface)详解

    万次阅读 多人点赞 2019-01-24 16:02:05
    接口(interface) 有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。 接口(interface)是抽象方法和常量值的定义的集合。 从本质上...

    接口(interface)

    有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。

    接口(interface)是抽象方法和常量值的定义的集合。

    从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。

    接口定义举例

    public interface Runner 
       int id = 1
       public void start()
       public void run()
       public void stop()    
    }
    

    案例:

    蝙蝠会飞,又会用牙齿咬

    首先定义一个飞行的接口:

    package cn.com.Classwork190124;
    
    /*
        如果一个类中,既有抽象方法,又有非抽象方法,那么该类只能定义为抽象类,不能定义为接口
        如果一个类中,只有抽象方法,没有非抽象方法,那么该类可以定义为接口
                                一般就定义为接口
        定义一个接口,使用interface关键字  接口,类,枚举,注解等都是java中的类型
        接口中所有的方法,都是抽象方法
            所以也可以说,接口就是一个特殊的抽象类
    
        接口中除了定义方法外,还可以定义成员变量
                    特点;方法和属性默认都是public修饰,也可以使用protected,但不能用private
                          所有的属性都是静态的常量,默认省略了static和final修饰符,属性的值必须实例化(初始化)
    
     */
    
    public interface Flyable {
        public final int wingsNumber = 2;
        public abstract void fly();
    
    }
    
    

    接着定义一个咬人的接口:

    package cn.com.Classwork190124;
    
    public interface Bitable {
        public int teethNumber = 0;
        public abstract void bite();
    }
    
    

    最后定义蝙蝠类去实现这两个接口:

    package cn.com.Classwork190124;
    
    /*
        在JAVA中,一个类无法继承自多个类,但是可以实现多个接口,使用关键字implements
                                            多个接口之间使用“,”隔开  多个接口之间,没有先后顺序
        这个类叫做实现类,这个类必须实现所有接口的所有方法
     */
    
    public class Bat implements Flyable,Bitable {
        @Override
        public void bite() {
            System.out.println("吸血");
        }
    
        @Override
        public void fly() {
            System.out.println("用翅膀飞");
        }
    
        public static void main(String[] args) {
            System.out.println(Flyable.wingsNumber);
        }
    }
    

    接口的特点:

    用 interface 来定义。

    接口中的所有成员变量都默认是由public static final修饰的。

    接口中的所有方法都默认是由public abstract修饰的。

    接口没有构造方法。构造方法用于创建对象

    实现接口的类中必须提供接口中所有方法的具体实现内容。

    多个无关的类可以实现同一个接口

    一个类可以实现多个无关的接口

    与继承关系类似,接口与实现类之间存在多态性

    接口也可以继承另一个接口,使用extends关键字。

    实现接口的类中必须提供接口中所有方法的具体实现内容。

    多个无关的类可以实现同一个接口

    一个类可以实现多个无关的接口

    与继承关系类似,接口与实现类之间存在多态性

    定义Java类的语法格式:

    < modifier> class < name> [extends < superclass>]

    [implements < interface> [,< interface>]* ] {

    < declarations>*

    }
    此外,接口还常常被用来当做定义常量的集合:

    package cn.com.Classwork190124;
    
    /*
        接口也经常用来被定义常量的集合  默认省略public static final
        定义更简单,使用更方便
     */
    
    public interface Power {
        int vol = 220;
        double hz = 50.0;
    }
    
    

    案例:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    如果实现接口的类中没有实现接口中的全部方法,必须将此类定义为抽象类。

    接口也可以继承另一个接口,使用extends关键字

    interface MyInterface
    
    {
    
    String s=“MyInterface”;
    
    public void absM1();
    
    }
    
    interface SubInterface extends MyInterface
    
    {
    
    public void absM2();
    
    }
    
    public class SubAdapter implements SubInterface
    
    {
    
    public void absM1(){System.out.println(“absM1”);}
    
    public void absM2(){System.out.println(“absM2”);}
    
    }
    

    JDK8新增接口中抽象方法的默认实现 使用default关键字

    package cn.com.Classwork190124;
    
    public interface Bitable {
        public int teethNumber = 0;
        //public abstract void bite();
        /*
        java新增接口中抽象方法的默认实现   使用default关键字
        加上default关键字后需要实现方法体
        子类中成为覆盖该方法
         */
        default void bite() {
            System.out.println("用牙齿咬");
        }
    }
    
    

    注意:如果实验发现明明用的是jdk8却报错为:Extension methods are not supported at language level '6’ 请进入idea file->project structure 在project选项卡下将图中被圈的部分改为8即可(language level不能比项目的jdk版本高)。
    在这里插入图片描述
    还可以附带static的默认实现方法

    package cn.com.Classwork190124;
    
    /*
        接口也经常用来被定义常量的集合  默认省略public static final
        定义更简单,使用更方便
     */
    
    public interface Power {
        int vol = 220;
        double hz = 50.0;
        /*
        jdk8新增功能
         */
        public static void lightOn(){
            System.out.println("默认的点灯方法");
        }
    
        public static void main(String[] args) {
            Power.lightOn();
        }
    }
    
    

    练习

    定义一个接口用来实现两个对象的比较。

    package cn.com.Classwork190124;
    
    public interface CompareObject<object> {
        public int compareto(object o);
        //若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
    }
    
    

    定义一个Circle类。

    package cn.com.Classwork190124;
    
    public class Circle {
        private double radius;
        private final double PI=3.14;
    
        public double findArea(){
            return PI*radius*radius;
        }
    
        public double getRadius() {
            return radius;
        }
    
        public void setRadius(double radius) {
            this.radius = radius;
        }
    }
    
    

    定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。

    package cn.com.Classwork190124;
    
    public class ComparableCircle extends Circle implements CompareObject<Circle> {
        @Override
        public int compareto(Circle o) {
            if(this.getRadius()==o.getRadius()){
                return 0;
            }else if(this.getRadius()<=o.getRadius()){
                return -1;
            }else {
                return 1;
            }
        }
    }
    
    

    定义一个测试类TestInterface,创建两个ComaparableCircle对象,调用compareTo方法比较两个类的半径大小。

    package cn.com.Classwork190124;
    
    import java.util.Scanner;
    
    public class TestInterface {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            ComparableCircle c1 = new ComparableCircle();
            ComparableCircle c2 = new ComparableCircle();
            c1.setRadius(sc.nextDouble());
            c2.setRadius(sc.nextDouble());
            System.out.println(c1.compareto(c2));
        }
    }
    

    思考:参照上述做法定义矩形类Rectangle和ComparableRectangle类,在ComparableRectangle类中给出compareTo方法的实现,比较两个矩形的面积大小。
    emmmmm换汤不换药我这里就不赘述了(绝对不是因为太懒!)。

    展开全文
  • 在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 接口并不是类,编写接口的方式和类很相似,但是它们属于不同...
  • 自定义注释@interface的用法理解

    千次阅读 2019-02-22 20:57:13
    场景:为了理解@interface使用 1.@interface自定义注解 &lt;1&gt;@interface自定义注解自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。 &lt;2&gt;在定义注解时,不能...
  • interface{} 与 []interface{}

    千次阅读 2017-08-18 16:30:44
    interface{} 与 []interface{} 区别
  • interface

    2019-04-04 04:32:51
    interface是什么 interface被称为接口,是一种类型,其本质是一组抽象方法的集合。凡是实现这些抽象方法的对象,都可以被称为“实现了这个接口”。其存在意义是为了规定对象的一组行为。 interface举例 package main...
  • @interface使用详解

    万次阅读 2019-08-21 17:25:25
    首先,@interface不是接口是注解类,在jdk1.5之后加入的功能,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节,我们通过反编译可以看到,源...
  • golang中interface{}转为struct

    万次阅读 2016-09-05 15:59:23
    es, ok := services["elasticsearch"].(*elasticsearch.ElasticSearchService) interface{}转为struct需要assert为指针
  • golang interface 转 string,int,float64

    万次阅读 2019-01-08 10:59:54
    func interface2String(inter interface{}) { switch inter.(type) { case string: fmt.Println("string", inter.(string)) break case int: fmt.Println("int", inter.(int...
  • golang interface类型转string等其他类型

    万次阅读 2018-07-17 10:40:32
    inter 是interface类型,转化为string类型是:  str := inter .(string) 转为其他类型也类似
  • adb interface usb driver(adb驱动 32bit&64bit) 绿色版

    万次下载 热门讨论 2020-07-27 12:26:36
    适用于插上usb线,手机adb连接不上,找不到adb interface驱动的情况.
  • golang interface{} 入参

    万次阅读 2018-05-04 11:00:06
    func sliceEqual(a, b []interface{}) bool { } a := []*Student{} b := []*Student{} sliceEqual(a, b) compile err: cannot use a (type []*Student) as type []interface {} in argument to sliceEqual golang...
  • 主要原因是因为在同一文件存在工程的不同的目录下,反复添加到工程里。造成重定义,解决办法是删除里重复的refrence就可以了。
  • JDK8新特性:函数式接口@FunctionalInterface的使用说明

    万次阅读 多人点赞 2017-01-06 14:03:34
    通过JDK8源码javadoc,可以知道这个注解有以下特点: 1、该注解只能标记在"有且仅有一个抽象方法"的接口上。 2、JDK8接口中的静态方法...如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
  • export interface和 class区别

    千次阅读 2018-08-28 18:02:31
    export interface 只是对一个东西的声明(不能具体的操作) export class 导出一个类 类里面可有有参数 可以有一写函数 方法(干一些具体的事情)
  • Go语言是门强类型语言,因此也导致了非常多的问题, interface{} 任意类型 不能随意的转换为其他类型 若要进行类型转换,需要进行类型的断言 示例代码: // Convert project main.go package main import ( ...
  • Adb interface驱动无法安装解决方法!

    万次阅读 2017-11-06 15:23:15
    今天在准备使用小米5进行真机测试,但是手机在插入电脑后...实际上Android SDK中带有Adb Interface的驱动,可以安装自带驱动。 其中驱动存放的位置为: D:\Android\SDK\extras\google\usb_driver\android_winusb.inf
  • 在电脑或手机升级,或更换电脑进行Android程序调试时,会出现找不到HDB Interface的情况,解决方案如下: 首先确认: 1,已开启开发者选项 2,已开启调试模式 3,已选择传输文件 4,连接线及硬件接口正常 仍有...
1 2 3 4 5 ... 20
收藏数 1,502,941
精华内容 601,176
关键字:

interface