英文:
Generic class instantiation using a bounded wildcard
问题
根据我之前的问题中列出的代码片段(从Gilad Bracha的Java泛型教程中复制),我编写了以下代码,尝试使用不同类型的对象填充名为history
的自定义泛型列表,该列表符合? extends Shape
的限制。但是,我的程序无法编译。为什么?它与我之前的问题中的代码片段有何不同?
import java.util.ArrayList;
class Shape {}
class Circle extends Shape {}
class Rectangle extends Shape {}
class MyArrayList<T>
{
private ArrayList<T> items = new ArrayList<>();
public T get(int idx)
{
return items.get(idx);
}
public void add(T item)
{
items.add(item);
}
@Override
public String toString()
{
String str = "A box of [";
for (T item : items) { str += item; }
str += ']';
return str;
}
}
public class Shapes
{
private static MyArrayList<? extends Shape>
history = new MyArrayList<>();
public static void main(String[] args)
{
history.add(new Circle());
history.add(new Rectangle());
System.out.println(history);
}
}
英文:
Based on the code snippet listed in my previous question (copied from a Java tutorial on generics by Gilad Bracha), I wrote the following code which tries to populate a custom generic list called history
with objects of different types conforming to the bound ? extends Shape
. However, my program doesn't compile. Why? How is it different from the code snippet in my other question?
import java.util.ArrayList;
class Shape {}
class Circle extends Shape {}
class Rectangle extends Shape {}
class MyArrayList<T>
{
private ArrayList<T> items = new ArrayList<>();
public T get(int idx)
{
return items.get(idx);
}
public void add(T item)
{
items.add(item);
}
@Override
public String toString()
{
String str = "A box of [";
for (T item : items) { str += item; }
str += ']';
return str;
}
}
public class Shapes
{
private static MyArrayList<? extends Shape>
history = new MyArrayList<>();
public static void main(String[] args)
{
history.add(new Circle());
history.add(new Rectangle());
System.out.println(history);
}
}
答案1
得分: 1
在你之前的例子中,你有一个 List<List<? extends Shape>>
。这里你有一个 List<? extends Shape>
。完全不同的东西。
给定一个 MyArrayList<? extends Shape>
,那是一个_引用_(就像通讯录中的一页,而不是房子),而'通讯录中的一页'(那将是你的变量)承诺你到达的房子将被保证是几种不同风格中的一种。具体来说,它将是一个 List<Shape>
。或者它可能是一个 List<Rectangle>
。或者可能是一个 List<Circle>
。但它将是各种形状的列表,或者某种特定形状的列表。
这与仅仅是'它是各种形状的列表'是不同的 - 那将是一个 List<Shape>
,而不是一个 List<? extends Shape>
。
鉴于它可能是一个圆的列表,它也可能是一个正方形的列表,你对 history
做的__一切__都必须是你可以对任一者做的事情。
.add(new Circle())
对于一个 List<Rectangle>
来说是无效的。因此,你不能这样做,history.add(new Circle())
是一个编译错误。
那么为什么之前的片段有效呢?因为那是关于 List<List<? extends Shape>>
的,这是一个与 List<? extends Shape>
完全不同的东西。一个存储形状。一个存储形状列表。
英文:
In your previous example, you had a List<List<? extends Shape>>
. Here you have a List<? extends Shape>
. Completely different things.
Given a MyArrayList<? extends Shape>
, that is a REFERENCE (like a page in an address book, not like a house), and the 'page in the address book' (that'd be your variable) promises that the house you get to will be guaranteed to be one of a few different style. Specifically, it'll be a List<Shape>
. Or it could be a List<Rectangle>
. Or perhaps a List<Circle>
. But it'll be either a list of all sorts of shapes, or a list of some sort of specific shape.
This is different from just 'it's a list of all sorts of shapes' - that would be a List<Shape>
, not a List<? extends Shape>
.
Given that it could be a list of circles, and it could also be a list of squares, everything you do with history
needs to be a thing you could do to either one.
.add(new Circle())
is not something that is valid for a List<Rectangle>
. Hence, you can't do that, and history.add(new Circle())
is a compilation error.
So why did the previous snippet work? Because that was about List<List<? extends Shape>>
which is a completely different thing to a List<? extends Shape>
. One stores shapes. One stores a list of shapes.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论