问题 带有钻石操作符的双括号初始化(匿名内部类)


我想知道为什么第二个地图声明(使用菱形运算符)在第一个地图声明时不会编译。编译错误:

错误:无法推断HashMap的类型参数;           map map2 = new HashMap <>(){     原因:不能在匿名内部类中使用“<>”     其中K,V是类型变量:       K扩展了在HashMap类中声明的Object       V扩展在类HashMap中声明的Object

码:

    Map<String, String> map1 = new HashMap<String, String>() { //compiles fine

        {
            put("abc", "abc");
        }
    };

    Map<String, String> map2 = new HashMap<>() { //does not compile

        {
            put("abc", "abc");
        }
    };

编辑
感谢您的回答 - 我应该更好地阅读编译错误。 我在那里发现了一些人 JLS

如果类实例创建表达式使用类的“<>”形式为类的类型参数声明一个匿名类,那么这是一个编译时错误。


12036
2018-03-19 16:13


起源

哪儿是 静态的 您的标题中提到的初始化程序? - Jon Skeet
@JonSkeet你是对的,不记得如何调用“双支撑”...... - assylias
错误是指一个 EnumMap,但你只有 HashMap在您的代码中。 - Steve Taylor
错误消息非常明显:您已经创建了一个匿名内部类 EnumMap。我认为,这是偶然的。 - biziclop
糟糕 - 它是一个实例初始化器,而不是静态初始化器。 - Steve Taylor


答案:


你没有 静态的 初始化程序在这里(关键字 静态的 完全失踪了)。

基本上你创建了一个新的匿名子类 HashMap 并在此处定义实例intializer块。顺便说一下,这才有效 HashMap 不是最终的。

因为你会得到一个匿名的子类 HashMap 钻石操作符在这里不起作用,因为子类将被编译,就像你写的那样 ... extends HashMap<Object, Object> 这显然不兼容 Map<String, String>


6
2018-03-19 16:18





钻石推理不适用于实例化匿名类,这就是你在这里所做的。

尝试这个:

Map<String, String> map1 = new HashMap<>();

{
    map1.put("abc", "abc");
}

4
2018-03-19 16:19





此功能是其中的一部分 项目硬币2 并将于2016年9月22日在Java 9中实现。

这是电话 Allowing the diamond syntax with some anonymous class constructors

链接。


3
2018-05-10 16:02



另见 bugs.openjdk.java.net/browse/JDK-8062373 - jcsahnwaldt


请注意你 可以 也完全省略了钻石。然而,虽然这是编译,但这只是因为它忽略了Java泛型并且倾向于Java向后兼容以前的版本。

Map<String, String> map1 = new HashMap() { //compiles fine
    {
        put("abc", "abc");
    }
};

1
2018-06-12 16:14



是的有效,但有警告...... - assylias
正确...从那以后 it's ignoring the Java generics - Jeff Fairley