使用有界通配符进行通用类实例化

huangapple go评论65阅读模式
英文:

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&lt;T&gt;
{
    private ArrayList&lt;T&gt; items = new ArrayList&lt;&gt;();

    public T get(int idx)
    {
        return items.get(idx);
    }

    public void add(T item)
    {
        items.add(item);
    }

    @Override
    public String toString()
    {
        String str = &quot;A box of [&quot;;
        for (T item : items) { str += item; }
        str += &#39;]&#39;;
        return str;
    }
}

public class Shapes
{
    private static MyArrayList&lt;? extends Shape&gt;
       history = new MyArrayList&lt;&gt;();
    public static void main(String[] args)
    {
        history.add(new Circle());
        history.add(new Rectangle());
        System.out.println(history);
    }
}

答案1

得分: 1

在你之前的例子中,你有一个 List&lt;List&lt;? extends Shape&gt;&gt;。这里你有一个 List&lt;? extends Shape&gt;。完全不同的东西。

给定一个 MyArrayList&lt;? extends Shape&gt;,那是一个_引用_(就像通讯录中的一页,而不是房子),而'通讯录中的一页'(那将是你的变量)承诺你到达的房子将被保证是几种不同风格中的一种。具体来说,它将是一个 List&lt;Shape&gt;。或者它可能是一个 List&lt;Rectangle&gt;。或者可能是一个 List&lt;Circle&gt;。但它将是各种形状的列表,或者某种特定形状的列表。

这与仅仅是'它是各种形状的列表'是不同的 - 那将是一个 List&lt;Shape&gt;,而不是一个 List&lt;? extends Shape&gt;

鉴于它可能是一个圆的列表,它也可能是一个正方形的列表,你对 history 做的__一切__都必须是你可以对任一者做的事情。

.add(new Circle()) 对于一个 List&lt;Rectangle&gt; 来说是无效的。因此,你不能这样做,history.add(new Circle()) 是一个编译错误。

那么为什么之前的片段有效呢?因为那是关于 List&lt;List&lt;? extends Shape&gt;&gt; 的,这是一个与 List&lt;? extends Shape&gt; 完全不同的东西。一个存储形状。一个存储形状列表。

英文:

In your previous example, you had a List&lt;List&lt;? extends Shape&gt;&gt;. Here you have a List&lt;? extends Shape&gt;. Completely different things.

Given a MyArrayList&lt;? extends Shape&gt;, 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&lt;Shape&gt;. Or it could be a List&lt;Rectangle&gt;. Or perhaps a List&lt;Circle&gt;. 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&lt;Shape&gt;, not a List&lt;? extends Shape&gt;.

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&lt;Rectangle&gt;. 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&lt;List&lt;? extends Shape&gt;&gt; which is a completely different thing to a List&lt;? extends Shape&gt;. One stores shapes. One stores a list of shapes.

huangapple
  • 本文由 发表于 2023年2月20日 00:07:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75501494.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定