因此,下面的函数应该是一个带有Car
对象并将其添加到Col<>
对象的函数。
void insertCar(List<? super Car> c, Car x) {
c.add(x)
}
问题是,是否将类型为n
的变量Nissan
的变量c
添加到类型为List<Car>
的变量insertCar(c, n)
中(即。Car
)
答案是肯定的,但我不确定原因。我认为由于super
的使用,无法添加对象Car
的子类型。它只需要Car
类型或List<>
的任何超类型。
任何能让我理解的人吗?
编辑是......
如果List<? super Car>
本身属于某个其他子类型,我将无法添加日产?例如,如果List<? super Ford>
实际上是var housecontroller = require("./controllers/housecontroller");
...
以下似乎存在相互矛盾的答案,但这是一个为考试复习提供的问题,因此请确保提供的问题和答案是正确的。只是我对它的理解是我不确定的。
答案 0 :(得分:1)
问题是,是否将类型为
n
的变量Nissan
的变量c
添加到类型为List<Car>
的变量insertCar(c, n)
中(即。public class GenericCheck { static void insertCar(List<? super Car> c, Car x) { c.add(x); } public static void main(String[] args) { List<Car> c = new ArrayList<>(); Nissan n = new Nissan(); insertCar(c, n); } } class Car {} class Nissan extends Car {}
)
要将您的文字写入代码,我相信这就是您所说的:
List<Car>
是。这很好,但需要进行3种类型的检查:
insertCar
List<? super Car>
Nissan
的有效第一个参数是insertCar
吗? 是,它是一个子类型,例如,请参阅here。Car
c.add(x)
x
的有效第二个参数是Car
吗? 是,这是一个子类型。Car
有效吗? 是,参数List<? super Car> c
必须是Car x
类型或Nissan
定义的超类型x
,定义是这样的Car
。那为什么会让人困惑?因为您传递给第二个参数Car
类型,而认为现在点3将会中断,因为Nissan
不属于Car
类型或超类型c.add(x)
(这是一个子类型)。会发生的事情是c
被提升为x
,这是一个可行的论据。
请记住,要知道调用c.add(x)
是否有效,您所要做的就是查看insertCar
和insertCar(List<? super Nissan> c, Car x)
的定义(在方法的参数列表中)。这可确保只要使用有效参数调用方法,调用List<Nissan>
就有效。在调用add(Car)
时,此检查与(两个)类型检查无关。这是我们上面进行的3次检查。
修改:为什么Car
不起作用?
因为类型擦除。在编译期间,编译器会擦除所有类型参数,并用其第一个边界替换每个参数(请参阅here)。您得到的是Nissan
到List<? super Car>
的请求。但这无法编译,因为List<Car>
不是add(Car)
的子类型。
在static void insertCar(List<? super Car /* or Nissan */> c, Car x) {
c.add(x);
}
的第一种情况下,键入删除会导致insertCar(..., Car)
,然后insertCar(..., Nissan)
有效。
我认为,最清楚你的困惑是认识到泛型提供仅编译时检查。正如我在上面提到的代码块
c.add(x)
无论在运行时中调用该方法的参数是什么,都必须编译。这意味着第一个方法参数中的泛型与传递给第二个参数的类型无关:Car
或==
不会影响return "";
的可编译性。给定的参数被转换(upcasted)到方法的参数类型""
,这与方法的内容无关。
答案 1 :(得分:0)
答案是肯定的,但我不确定原因。我想加入了亚型 因为超级的使用,汽车是不可能的。那 它只会采用Car类型或Car的任何超类型。
任何超类引用都可以保存其实例的对象或其任何子类实例,因此这是完全合法的。
答案 2 :(得分:0)
您的子类型objet将至少具有Car对象中的所有属性和方法,通常还有更多自己的方法。如果将Nissan对象分配给Car变量,则可以调用Car变量的所有方法。相反,将Car实例分配给Nissan对象是不可能的,因为Nissan对象可能有比Car实例更多的方法。