简体   繁体   English

为什么 Java 7 菱形运算符不能与匿名类一起使用?

[英]Why can't Java 7 diamond operator be used with anonymous classes?

Consider this Java code which attempts to instantiate some List s:考虑这个 Java 代码,它试图实例化一些List

List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<String>() { };
List<String> list4 = new ArrayList<>() { };
List<String> list5 = new ArrayList<Integer>() { };

list1 and list2 are straightforward; list1list2很简单; list2 uses the new diamond operator in Java 7 to reduce unnecessary repetition of the type parameters. list2使用 Java 7 中新的菱形运算符来减少不必要的类型参数重复。

list3 is a variation on list1 using an anonymous class, potentially to override some methods of ArrayList . list3list1的变体,使用匿名 class,可能会覆盖ArrayList的某些方法。

list4 attempts to use the diamond operator, similar to list2 , but this is a compile error, with the message '<>' cannot be used with anonymous classes . list4尝试使用类似于list2的菱形运算符,但这是一个编译错误,消息为'<>' cannot be used with anonymous classes

list5 produces an error that proves the compiler knows what type is actually needed. list5产生一个错误,证明编译器知道实际需要什么类型。 The error message is Type mismatch: cannot convert from new ArrayList<Integer>(){} to List<String>错误信息是Type mismatch: cannot convert from new ArrayList<Integer>(){} to List<String>

So, with the declaration of list4 , why can't the diamond operator be used with anonymous classes?那么,有了list4的声明,为什么菱形运算符不能与匿名类一起使用呢? There is a similar question here with an accepted answer that contains the following explanation from JSR-334 :这里有一个类似的问题,接受的答案包含来自JSR-334的以下解释:

Using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change.不支持将菱形与匿名内部类一起使用,因为这样做通常需要扩展 class 文件签名属性以表示不可表示的类型,这是事实上的 JVM 更改。

I need some help understanding that reasoning.我需要一些帮助来理解这个推理。 Why would an explicit type versus the identical and apparently easily inferred type require any difference in the resulting class file?为什么显式类型与相同且显然很容易推断的类型需要在生成的 class 文件中有任何差异? What difficult use case would be covered by "doing so in general"? “通常这样做”将涵盖哪些困难的用例?

What is the underlying reason for this?这背后的根本原因是什么?

This was discussed on the "Project Coin" mailing list .在“Project Coin”邮件列表中进行了讨论。 In substance (emphasis mine):实质上(强调我的):

Internally, a Java compiler operates over a richer set of types than those that can be written down explicitly in a Java program.在内部,Java 编译器操作的类型比可以在 Java 程序中显式写下的类型更丰富。 The compiler-internal types which cannot be written in a Java program are called non-denotable types.不能在 Java 程序中编写的编译器内部类型称为不可表示类型。 Non-denotable types can occur as the result of the inference used by diamond.作为钻石使用的推理的结果,可能会出现不可表示的类型。 Therefore, using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change .因此,不支持将菱形与匿名内部类一起使用,因为这样做通常需要对类文件签名属性进行扩展以表示不可表示的类型,这是事实上的 JVM 更改 It is feasible that future platform versions could allow use of diamond when creating an anonymous inner class as long as the inferred type was denotable.只要推断的类型是可表示的,未来的平台版本就可以在创建匿名内部类时允许使用菱形。

Note that it is not supported in Java 8 either but will be included as a new feature in Java 9 (Item 3 of "Milling Project Coin" ).请注意,它在 Java 8 中也不支持,但将作为 Java 9 中的一项新功能包含在内( “Milling Project Coin”的第 3 项)。

You can use diamond opeator in Java9您可以在Java9 中使用菱形运算

MyHandler<Integer> intHandler = new MyHandler<>(1) {

        @Override
        public void handle() {
            // handling code...
        }
    };

    MyHandler<? extends Integer> intHandler1 = new MyHandler<>(10) {

        @Override
        void handle() {
            // handling code...
        }
    };

    MyHandler<?> handler = new MyHandler<>("One hundred") {

        @Override
        void handle() {
            // handling code...
        }
    };
}

You can use it in java 9 Example Diamond operator您可以在 java 9 Example Diamond 运算符中使用它

 MyHandler<Integer> intHandler = new MyHandler<>(1) {

        @Override
        public void handle() {
            // handling code...
        }
 };

From Java 10 , you can do easily with var , the compiler will take care of the Type inference.Java 10 开始,您可以使用var轻松完成,编译器将负责类型推断。

var list1 = new ArrayList();
var list2 = new ArrayList<String>();
var list3 = new ArrayList<String>() { };
var list4 = new ArrayList<>() { };
var list5 = new ArrayList<Integer>() { };

From Java 9, diamond operator <> can be used with anonymous classes.来自Java 9、菱形运算符<>可以和匿名类一起使用。 See here .这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么不能在匿名内部类上使用菱形推断类型? - Why can't diamond infer types on anonymous inner classes? 为什么在Java 7中使用菱形运算符进行类型推断? - Why diamond operator is used for Type Inference in Java 7? 为什么Java 7和Eclipse 3.8编译器不能用新的Java 7菱形运算符编译JDK代码? - Why can't the Java 7 and Eclipse 3.8 compiler compile JDK code with the new Java 7 diamond operator? 为什么菱形运算符不能在Java 7中的addAll()调用中工作? - Why doesn't the diamond operator work within a addAll() call in Java 7? Java 7钻石运营商:为什么难以实施? - Java 7 diamond operator: why was it difficult to implement? 不能使用来自同一个 class 的 2 个具有不同钻石运算符类的模拟 - Can't use 2 Mocks from the same class with different diamond operator classes Cobertura无法识别Java 1.7 Diamond运算符 - Cobertura Can Not Recognize Java 1.7 Diamond Operator 在Java 7中使用菱形运算符 - Using diamond operator in Java 7 为什么带有共同祖先的钻石案例用于解释Java多重继承问题,而不是两个不相关的父类? - Why is the diamond case with its common ancestor used to explain Java multiple inheritance issue, instead of two unrelated parent classes? Java中如何使用匿名内部类? - How are Anonymous inner classes used in Java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM