当我继续学习在线教程时,我发现了这一课。我有一个接口和两个实现该接口的类。
public interface Payable {
double getPaymentAmount();
}
和
Invoice
,用于实现上述接口Payable
SalariedEmployee
,它扩展了实现Employee
接口的抽象类Payable
。 现在在测试类中,在创建对象数组时,对象的类型称为Payable[]
而不是SalariedEmployee[]
或Invoice[]
,如
public static void main(String[] args) {
Payable[] payableObjects = new Payable[4];
payableObjects[0] = new Invoice("0000", "abc", 1,2);
payableObjects[1] = new SalariedEmployee("test", "user", "000-000", 35);
答案 0 :(得分:4)
你的问题标题不是语法,但选择一词表明对概念的细微误解。
您只能创建一个类作为该类。也就是说,您无法编写new Payable
,并且不知何故可能会创建任何Invoice
或SalariedEmployee
个对象。
但是你可以引用Payable
指向任何实现Payable
的对象。这几乎是亚型多态性的基本思想。
示例中的内容是创建了四个Payable
引用的数组。这些引用尚未指向任何内容(它们为空)并且还没有Invoice
或SalariedEmployee
个对象,只有数组对象。
然后,代码创建两个对象并将它们分配给两个引用。这与数组元素是独立变量的情况相同。 (差不多,但不同之处在于数组协方差,此时这并不重要。)特别是new
运算符的结果在第一种情况下的类型为Invoice
,而不是{ {1}}。您可以将Payable
分配给Invoice
引用,但转换是在分配时进行的,而不是在创建时进行的。
从技术上讲,标题问题的答案是“不,对象总是按照您在Payable
表达式中指定的类型创建,但您可以在之后转换引用”。
答案 1 :(得分:1)
对于你的第一个问题:是的,如果不是这样,你会得到一个编译器错误。
对于第二种情况,请以List
或Map
为例。请看下面的例子。我们声明了一个列表但是根据标志,我们希望这个特定的List
行为不同,因为它代表一个不同的类
public class BookList{
List <String> list;
public BookList(boolean flag) {
if(flag) {
list = new ArrayList<>();
} else {
list = new LinkedList<>();
}
}
}
由于我们将其声明为List
,因此我们可以分配实现此interface
的不同类型的列表。您可以非常简单地更改此类的用例,同时您仍然可以访问该接口提供的每个方法。
这就是你的Payable
阵列正在做的事情。您希望将不同类型的类分配到此数组中,这些类都实现此接口。
这样可以更轻松地为此特定界面创建方法。以求和方法为例说明。
public int sumPayable(Payable[] payables) {
int sum = 0;
for(Payable p : payables) {
sum += p.getPaymentAmount();
}
return sum;
}
在这种情况下,实现Payable
的每个类的实际类都是无关紧要的,因为你可以简单地将一个数组传递给这个方法,就像你创建的那样。