在Java中实例化接口

时间:2013-05-25 14:58:23

标签: java interface abstract

我有这个界面:

public interface Animal {
    public void Eat(String name);
}

这段代码实现了接口:

public class Dog implements Animal {
    public void Eat(String food_name) {
        System.out.printf(food_name);
    }

    public static void main(String args[]) {
        Animal baby2 = new Dog(); //HERE!!!!!!!!!!!!!!!!!!!!!!
        baby2.Eat("Meat");
    }
}

我的问题是,为什么代码有效?无法实例化接口。然而在这种情况下,界面被实例化(标记为“HERE !!!!!!!!!!!!!!”)。

这里发生了什么?

15 个答案:

答案 0 :(得分:33)

不,不是 - 您正在实例化Dog,但由于DogAnimal,您可以将变量声明为Animal。如果您尝试实例化接口Animal,那么它将是:

Animal baby2 = new Animal();

试试看,并惊恐地看着编译器尖叫:)

答案 1 :(得分:18)

Dog不是界面:Dog实现 Animal界面。

这里没有什么不可思议的事情。


请注意,您可以实例化接口的匿名实现,如下所示:

Animal animal = new Animal() {
    public void Eat(String food_name) {
        System.out.printf("Someone ate " + food_name);
    }
};

答案 2 :(得分:10)

让我们考虑以下代码:

interface Cookable {
    public void cook();
}

class Food {
    Cookable c = new Cookable() {
     public void cook() {
         System.out.println("anonymous cookable implementer");
        }
      };
 }

前面的代码创建了一个匿名内部类的实例,但是在这里,新的实时类是可建模接口的实现者。请注意,这是您唯一能看到语法的时间:

new Cookable()

其中Cookable是一个接口而不是nonabstract类类型。想一想: 您无法实例化界面,但这就是代码所做的事情。但是,当然,它没有实例化Cookable object - 它正在创建新anonymous implementer of Cookable的实例。

  

您可以阅读以下这一行:

   Cookable c = new Cookable(){}
  

as"声明一个Cookable类型的引用变量,显然,它将引用一个类中的对象   实现可烹饪界面。但是,哦,是的,我们还没有   一个实现可食用的类,所以我们要做一个正确的   在这里,现在。我们不需要这个班级的名字,但它将是一个   实现可食用的类,这个花括号开始   新实施班的定义。"

重要的是要记住匿名接口实现者 - 他们只能实现一个接口。根本没有任何机制可以说你的匿名内部类将实现多个接口。实际上,匿名内部类甚至不能扩展类并同时实现接口。 innve类必须选择成为命名类的子类,而不是直接实现任何接口或实现单个接口。

所以不要被实例化接口的任何尝试所欺骗,除非是匿名内部类。 以下内容不合法:

Runnable r = new Runnable(); // can't instantiate interface 

而以下是合法的,因为它实例化了Runnable接口的实现者(匿名实现类):

Runnable r = new Runnable() { 
   public void run(){ }
};

您可以阅读我的文章here

答案 3 :(得分:8)

您在此处观察的是Dependency inversionSOLID方面。

您的代码依赖于Animal合同的抽象,通过实例化它的具体实现。你只是说,“我正在即时一些对象,但无论该对象实际是什么,它都将绑定到{{1}的契约} interface。“

举例来说,这些声明:

Animal

在这两种情况下,列表和地图的主要方面是它们遵循List<String> wordList = new LinkedList<>(); Map<Integer, String> mapping = new HashMap<>(); List的通用合同。

答案 4 :(得分:2)

Animal baby2 = new Dog(); //HERE!!!!!!!!!!!!!!!!!!!!!!

当然你没有实例化动物。您只是将Dog实例引用到它。 在java中我们可以使用超类引用。

答案 5 :(得分:1)

接口Animal未实例化,但由Dog实现。Dog已实例化

答案 6 :(得分:1)

当你说:

Animal baby2 = new Dog();

引用类型是Animal(接口),它指向具体实现(Dog)。对象类型Dog是具体的,可以实例化。在这种情况下,只要Dog hasanimal指向Dog。

的参考类型是接口中所有方法的具体实现

如果你做了类似的事,

Animal baby2 = new Animal(); // here you are actually instantiating

这将是无效的,因为现在您正在尝试从抽象实现中创建具体对象。

答案 7 :(得分:1)

Interface Animal充当Dog类的数据类型。您实际上是在实例化Dog类而不是接口或它的数据类型。

答案 8 :(得分:1)

这是多态的情况,看起来你正在创建'Animal'对象,但事实并非如此。您正在创建“运行时”计算的“狗”对象。“动物”作为合同。接口不能直接实例化,但可以通过向上转换其子类来用作类型。您还可以使用匿名类将对象实例化为“Animal”类型。

   Animal baby2 = new Dog(); //upcasting polymorphically
   Animal baby3=new Animal(){
      public void Eat(String food){System.out.println("fdkfdfk"); }
   }
    //You can instantiate directly as anonymous class by implementing all the method of interface

答案 9 :(得分:1)

要了解更广泛的图片:

Animal [] Zoo = new Animal[10] ; // is also correct

但为什么?

整个想法是,在上表中你可以放10只不同类型的动物。唯一的条件是进入动物园的所有动物都必须实现动物界面。

public interface Animal {
 void Eat();
}
class Wolf implements Animal {  void Eat (){ 
System.out.println("Wolf eats meat ") ;}}

Class Zebra implements Animal{ void Eat (){
System.out.println("Zebra eats the grass ") ;}}

class test {
public static void main (String args []) {

Animal [] Zoo = new Animal[2] ;

Zoo[0] =  new Wolf() ;
Zoo[1] = new Zebra() ;

 //so you can feed your animals in Zoo like this

 for (int i=0 ; i<Zoo.lenght;i++) {Zoo[i].Eat();}
}
}

答案 10 :(得分:0)

实际上你可以实例化界面。这是您可以尝试的代码

public static void main(String args[]) {
    System.out.println(new Animal() {
        public String toString() {
            return "test";
        }
    });
}

此程序成功运行并打印test 试试吧。

答案 11 :(得分:0)

这里只是引用接口,但实例化仅由类完成。 例如

Animanl a =新狗 动物a - 变量被引用 新狗 - 现在分配记忆

答案 12 :(得分:0)

您无法实例化接口。可以认为该功能类似于抽象类的功能。您可以引用该接口,但不能创建接口的对象。如果您做这样的事情......

动物a = new Animal(); 编译器将显示错误-“无法实例化Animal类型”。

答案 13 :(得分:0)

使用Java 8功能接口

@FunctionalInterface // this is not mandatory 
interface A{
    void m1(); // only one abstract method allowed for functional interface
}

class Main{
   public static void main(String a[]){

      // old usage
      A a1 = new A(){
        @Override
        public void m1(){
           System.out.println("Call Me normally");
        }
      };

      a1.m1();

      // new in java 8, functional interface
      A a2 = ()-> System.out.println("Call Me as functional interface");
      a2.m1();
 
   }
}

答案 14 :(得分:0)

你所做的是类型转换。您已经创建了一个 dog 类的实例,并将它的类型转换为接口动物。它是运行时多态性的一个例子。但是是的,可以实现一个接口,我在搜索时到达了这里。 即

public class demo16{
interface cardio{
    void run();
}

static void foo(){
    cardio c = new cardio(){ //HENCE instance of "interface cardio" is being created inside a method foo
        public void run(){
            System.out.println("How you doing  ! ");
        }; //HENCE observe the ";" beside }
    };     //HENCE observe the ";" beside }
    c.run();
}

public static void main(String [] args){
    foo();
}

}