不同difference
类型的两个变量之间的interface
是什么,但实际上是使用same object
实例化的。
例如,A类实现接口I1 I2。
interface I1 {}
interface I2 {}
class A implements I1, I2 {
...
}
然后我将类A的实例转换为接口类型I1,并将另一个A转换为类型I2
I1 a1 = new A();
I2 a2 = new A();
a1
和a2
之间有什么区别?类型a1
的{{1}}无法调用声明为接口I1
的方法
答案 0 :(得分:1)
a1
和 a2
是不同的对象。
例如:
interface I1 {
public void derp();
}
interface I2 {
public void herp();
}
你有
I1 a1 = new A();
I2 a2 = new A();
a1
指的是类实现I1
,因此a1
只能调用I1
中定义的方法derp()
。它无法调用derp()
,因为derp()
中定义了I2
。由于同样的原因,a2
只能调用herp()
而不能调用derp()
。
注意:虽然a1
和a2
是不同的对象,但如果class A
实现I1
和I2
中的所有方法,则它们没有区别{1}}然后a1
和a2
可以采取相同的行动。但它们仍然是两个独特的对象
答案 1 :(得分:0)
a1
和a2
都引用A
类型的对象。区分"声明的类型"是非常重要的。变量的变量,以及它引用的对象的实际类型(如果变量不是null)。
宣布
时I1 a1 = <anything>;
或只是
I1 a1;
编译器唯一知道的a1
是它必须引用一些实现I1
的对象。因此,如果为接口a1.method(...)
(或超级接口或I1
)声明了方法,则只能调用方法Object
。此外,a1
只能分配给另一个声明为I1
的变量(或超级接口,或Object
),如果您将其用作参数
x.someOtherMethod(a1);
仅当参数类型为I1
或超级接口或Object
时才合法。
请注意,将其初始化为new A()
并没有什么不同。出于&#34;允许编译器了解变量&#34;的原因,不考虑初始表达式。 (您可以使用代码将a1
分配给不同类型的对象。但即使变量为final
,也会应用相同的规则。)
但是,您可以让编译器通过强制转换将其视为另一种类型。将接口变量强制转换为任何其他接口始终是合法的,因为某些类可以在某个地方实现这两个接口。因此,这是合法的:
I2 x = (I2)a1;
在运行时,编译器将检查a1
是否引用除I2
之外还实现I1
的对象。如果是这样,演员就会成功。如果不是,则抛出异常。假设没有例外,(I2)a1
现在可以以任何其他I2
可以使用的方式使用。因此,如果I2
定义方法methodOfI2
,您可以说
((I2)a1).methodOfI2(...parameters...)
答案 2 :(得分:0)
用一个具体的例子来思考:
public class PetDog implements FeedableAnimal, PettableAnimal {
...
}
...
FeedableAnimal dog = new PetDog();
现在,如果我将PetDog实例化为FeedableAnimal,我就无法调用PettableAnimal中定义的任何方法。那是因为PetDog现在只表现得像FeedableAnimal。我们无法知道PetDog是Pettable,因为我们没有将它实例化为PettableAnimal。
对术语的澄清:我们不是&#34;铸造&#34; PetDog到FeedableAnimal。我们只是说在编译时,dog就像一个FeedableAnimal。在运行时,dog仍然在PetDog中承担定义的行为。