我有这个界面:
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 !!!!!!!!!!!!!!”)。
这里发生了什么?
答案 0 :(得分:33)
不,不是 - 您正在实例化Dog
,但由于Dog
是Animal
,您可以将变量声明为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 inversion的SOLID方面。
您的代码依赖于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();
}
}