在Java中实例化接口
我有这个界面:
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 !!!!!!!!!!!!!!”)。
这里发生了什么?
不,它不是 – 你正在实例化一只Dog
,但由于一只Dog
是Animal
,你可以将变量声明为Animal
。 如果您尝试实例化Animal
接口,它将是:
Animal baby2 = new Animal();
试试看,惊恐地看着编译器尖叫:)
Dog
不是一个接口: Dog
是一个实现 Animal
接口的类。
这里没有什么不可思议的事情发生。
请注意,您可以实例化接口的匿名实现,如下所示:
Animal animal = new Animal() { public void Eat(String food_name) { System.out.printf("Someone ate " + food_name); } };
你在这里观察的是SOLID的依赖倒置方面。
您的代码依赖于Animal
契约的抽象,通过实例化它的具体实现。 你只是在说,“我正在对某个对象进行即时消息,但无论该对象实际上是什么,它都将受到Animal
接口的约束。”
举例来说,这些声明:
List wordList = new LinkedList<>(); Map mapping = new HashMap<>();
在这两种情况下,列表和地图的主要方面是它们遵循列表和地图的通用合同。
我们考虑下面的代码:
interface Cookable { public void cook(); } class Food { Cookable c = new Cookable() { public void cook() { System.out.println("anonymous cookable implementer"); } }; }
上面的代码创建了一个匿名内部类的实例,但是在这里,新的实时类是Cookable接口的实现者。 请注意,这是您唯一能看到语法的时间:
new Cookable()
Cookable是一个接口而不是nonabstract类类型。 想一想: 你不能实例化一个接口 ,但这就是它正在做的代码。 但是,当然,它并没有实例化一个Cookable object
– 它正在创建一个新anonymous implementer of Cookable
。
你可以读这一行:
Cookable c = new Cookable(){}
as“声明一个Cookable类型的引用变量,显然,它将引用一个实现Cookable接口的类中的对象。但是,哦,是的,我们还没有一个实现Cookable的类,所以我们要去现在就在这里做一个。我们不需要该类的名称,但它将是一个实现Cookable的类,这个大括号开始新实现类的定义。
重要的是要记住匿名接口实现者 – 他们只能实现一个接口。 根本没有任何机制可以说你的匿名内部类将实现多个接口。 实际上,匿名内部类甚至无法扩展类并同时实现接口。 innve类必须选择要么是命名类的子类,要么根本不直接实现任何接口,要么实现单个接口。
所以不要被实例化接口的任何尝试所欺骗,除非是匿名内部类。 以下是不合法的:
Runnable r = new Runnable(); // can't instantiate interface
而以下是合法的,因为它实例化了Runnable接口的实现者(匿名实现类):
Runnable r = new Runnable() { public void run(){ } };
你可以在这里阅读我的文章。
Animal baby2 = new Dog(); //HERE!!!!!!!!!!!!!!!!!!!!!!
当然你没有实例化动物。 您只是将Dog实例引用到它。 在java中我们可以采用超类引用。
接口Animal
不是被实例化的,而是由Dog
实现的。并且一个Dog
被实例化
当你说:
Animal baby2 = new Dog();
引用类型是Animal(接口),它指向具体的实现(Dog)。 对象类型Dog是具体的,可以实例化。 在这种情况下,只要Dog hasanimal指向Dog。 在接口中的所有方法的具体实现,您可以使一个引用类型
如果你做了类似的事情,
Animal baby2 = new Animal(); // here you are actually instantiating
这将是无效的,因为现在您正在尝试从抽象实现创建具体对象。
Interface Animal充当Dog类的数据类型。 您实际上是在实例化Dog类而不是接口或它的数据类型。
要有更广泛的图景:
Animal [] Zoo = new Animal[10] ; // is also correct
但为什么 ?
整个想法是,在上表中你可以放置10种不同类型的动物。 唯一的条件是进入动物园的所有动物都必须实现Animal的界面。
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
这是多态的情况,看起来你正在创建’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
实际上你可以实例化界面。 这是您可以尝试的代码
public static void main(String args[]) { System.out.println(new Animal() { public String toString() { return "test"; } }); }
该程序运行成功并打印test
试试吧。
这里只是引用接口,但实例化仅由类完成。 例如
Animanl a =新的Dog Animal a – 变量被引用为新的Dog – 现在已经分配了Memory