我正在尝试一个简单易懂的有关Java逆向的示例,并且对问题有所了解。
在下面的示例中,我有List<? super CarBill> list1
。我的理解是,我应该能够添加CarBill
的任何超类的对象。通过这种逻辑,我应该能够向其添加Bill
类的对象吗?
我收到编译错误。
package Generics;
import java.util.ArrayList;
import java.util.List;
public class VarianceTests {
static class Bill{
String vName;
String type;
Bill(String vName){
this.vName=vName;
}
Bill(String vName,String type){
this.vName=vName;
this.type=type;
}
}
static class CarBill extends Bill{
String name;
CarBill(String name)
{
super(name,"Car");
}
}
static class Car<T extends Bill> {
T car;
Car(T car){
this.car=car;
}
String getNameOfCar() {
return car.vName;
}
}
public static void main(String args[]) {
CarBill cBill = new CarBill("Baleno");
Bill bill=new Bill("Whatever");
Car car = new Car(bill); //cBill is valid too as Car accepts <? extends Bill>
List<? super CarBill> list1 = new ArrayList<>();
list1.add(cBill);
list1.add(bill);
}
public void acceptListOfCars(List<? extends Bill> list1) {
Bill b = list1.get(0); //Valid syntax
}
}
答案 0 :(得分:2)
不太。
让我们从以下代码开始:
List<Integer> listOfInts = new ArrayList<Integer>();
List<Number> listOfNumbers = listOfInts;
listOfNumbers.add(5.5D); // a double
int i = listOfInts.get(0); // uhoh!
以上代码实际上不会编译;第二行是无效的分配。您的思路会说:但是..为什么呢? Number是Integer的超类型,因此,整数列表也很容易成为数字列表,不是吗?但是第三行显示了为什么这一行推理不正确。 Java不允许您编写以上代码。您可以写的是:同一件事,但是这次我们调整第二行:
List<Integer> listOfInts = new ArrayList<Integer>();
List<? extends Number> listOfNumbers = listOfInts;
listOfNumbers.add(5.5D); // a double
int i = listOfInts.get(0); // uhoh!
这一次,您在第三行收到编译器错误:您不能在此列表中添加双精度型。但是,如果您从中读取,则会得到数字(而不是对象)。一切都很好:无论我们尝试什么,上面的代码片段都永远都不能编译,因为它试图将双精度数添加到一个int列表中。
要点是:List<? extends Number>
并不表示:“此列表包含数字或其任何子类型”。没有;就像List x = new ArrayList()是合法的Java一样,List<Number>
的意思是“此列表包含数字或其任何子类型”,因为任何数字子类型的任何实例本身都可以用作数字。 List<? extends Number>
的意思是:该列表被限制为仅包含某些特定类型的实例,但该类型未知。众所周知,无论该类型是什么,它都是Number或其子类型。
因此,您不能将任何内容添加到List<? extends Number>
。
超级,类似的故事:
List<? super CarBill>
的含义:这是一个列表,仅限于包含某些特定类型的实例,但该类型未知。已知的是,无论是哪种类型,它都是CarBill或其某些SUPER类型。
这样做的好处是,您可以将CarBill
实例添加到List<? super CarBill>
变量中。当您从中读取内容时,您会拿出物品。
答案 1 :(得分:2)
您的理解是错误的。
List<? super CarBill>
表示该列表可以是CarBill
或CarBill
本身的任何超类的列表。它可能是List<Object>
,可能是List<Bill>
,甚至可能是List<CarBill>
。实际上是哪一个?我们不知道。
因此,您不能将Bill
添加到List<? super CarBill>
,因为如果列表实际上是List<CarBill>
怎么办?您不能将Bill
添加到List<CarBill>
。
换句话说,您只能将CarBill
或CarBill
的子类添加到List<? super CarBill>
中。
如果您打算创建一个可以存储任何类型的Bill
的列表,则可以创建一个List<Bill>
。
This post也可能有帮助。
答案 2 :(得分:1)
我的理解是,我应该能够添加任何CarBill超类的对象
否。
List<? super CarBill>
不是将接受CarBill
的任何超类型对象的列表。该列表将接受CarBill
的某些 specific 超类型的对象,但是尚不清楚哪个超类型。
您可以添加任何类型为CarBill
的对象,因为可以保证它是类型为?
的子类型。但是不不能保证CarBill
的超类型是?
的子类型。
例如:
List<? super CarBill> myList = new ArrayList<Bill>();
Object o = "Anything";
Object
是CarBill
的超类型。因此,如果您可以在列表中添加 CarBill
的任何超类型,则可以在列表中添加o
,这意味着您可以添加任何内容< / em>到列表。