【问题标题】:Java Generics putting on Map<String, ? extends List<String>>Java 泛型放在 Map<String, ?扩展列表<字符串>>
【发布时间】:2010-10-26 16:06:05
【问题描述】:

有没有办法以类型安全的方式进行以下实现?

public void myMethod( Map<String, ? extends List<String>> map )
{
   map.put("foo", Collections.singletonList("bar");
}

上述实现不起作用。它需要Map&lt;String, ? super List&lt;String&gt;&gt; 才能正确编译方法map.put()。但是 myMethod 不会以这种方式接受 List 的任何子类型。所以,我必须改用Map&lt;String, ? extends List&lt;String&gt;&gt;。如何以类型安全的方式解决此问题?

【问题讨论】:

    标签: java generics list collections map


    【解决方案1】:
    public void myMethod( Map<String, List<String>> map ) {
        map.put("foo", Collections.singletonList("bar") );
    }
    

    您不能将ListCollections.singletonList() 的返回类型放入? extends ListMap,因为实际类型可以是List 的任何实现。例如,它是 将通用 List 放入 Map&lt;String,LinkedList&gt; 是不安全的,因为 List 可能不是 LinkedList。但是,我们可以轻松地将 LinkedList 放入 Map&lt;String,List&gt; .

    我认为你在考虑你的泛型。对于非泛型类,您不必使用 ? extends。例如,List&lt;Object&gt; 将包含任何Object? extends 不需要添加对象。 List&lt;List&lt;Foo&gt;&gt; 将只接受 List&lt;Foo&gt; 对象而不接受 List&lt;FooSubclass&gt; 对象 [泛型类不会根据其参数继承]。这就是? extends 发挥作用的地方。要将List&lt;Foo&gt;List&lt;FooSubclass&gt; 添加到List,类型必须是List&lt;List&lt;? extends Foo&gt;&gt;

    【讨论】:

    • +1 以获得很好的解释(现在您的泛型是可见的:P)。
    • 糟糕。我一直在想,因为 SOF 无论如何都会过滤文本,所以它修复了尖括号的东西。哦,好吧...
    【解决方案2】:

    Map&lt;String, List&lt;String&gt; 不工作吗?有什么特别的原因你必须在那里有一个通配符吗?

    【讨论】:

      【解决方案3】:

      想象一下,如果有人给你一个Map&lt;String, ArrayList&lt;String&gt;&gt;。您输入的值是 Collections.singletonList 的结果,不是ArrayList

      您不能在 Map 中接受 List 的任何子类型,然后期望能够添加您自己的(可能不兼容的)子类型。

      【讨论】:

        【解决方案4】:

        同时使用集合和泛型有一个非常简单的原则。它被称为“获取和放置原则”:

        当您只从集合中获取值时使用“扩展”通配符,当您只将值放入集合时使用“超级”通配符,当您想要获取和放置时不要使用任何通配符。

        所以,如你所见,根据这个原则,最初的例子是无效的。

        【讨论】:

          猜你喜欢
          • 2012-04-06
          • 2017-04-17
          • 1970-01-01
          • 2021-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多