简体   繁体   English

Java泛型接口实现不能省略类型参数?

[英]Java generic interface implementation cannot omit type parameter?

I found that in Java I could use anonymous class to implement interface like Runnable (non-generic).我发现在 Java 中我可以使用匿名类来实现像 Runnable(非泛型)这样的接口。 I could also declare a variable without specifying type parameter on the right of "=".我也可以声明一个变量而不在“=”右侧指定类型参数。 But I found for generic type, I cannot omit this:但是我发现对于泛型类型,我不能省略这个:

import java.util.ArrayList;
import java.util.List;
interface Normal {
    Integer f();
    void g();
}
interface Generic<T> {
    T f();
    void g();
}
public class GenericInterface {
    public static void main(String[] args) {
        List<Integer> li = new ArrayList<>(); // ArrayList without type parameter, OK
        Runnable r = new Runnable() {
            @Override public void run() {}
        };
        Normal n = new Normal() { // declare implementation, OK.
            @Override public Integer f() {
                return new Integer(0);
            }
            @Override public void g() {}
        }; 
        Generic<Integer> i = new Generic<>() { // Why need type paramter here?
            @Override public Integer f() {
                return new Integer(0);
            }
            @Override public void g() {}
        };
    }
}

As you could see, javac report compilation failure for this line:如您所见,javac 报告此行的编译失败:

Generic<Integer> i = new Generic<>() {

While the compiler is smart enough to compile List<Integer> li = new ArrayList<>() , when compiler already know the real type from the left of this statement, why it still needs me to write new Generic<Integer>() { ?虽然编译器足够聪明,可以编译List<Integer> li = new ArrayList<>() ,但当编译器已经知道这条语句左侧的真实类型时,为什么它仍然需要我编写new Generic<Integer>() { ?

Or Java prevents generic interface implementation without specifying the type parameter?还是Java在不指定类型参数的情况下阻止泛型接口实现? What is the reason?是什么原因?

In Java 8 the compiler gives this error:在 Java 8 中,编译器给出了这个错误:

GenericInterface.java:23: error: cannot infer type arguments for Generic<T>
        Generic<Integer> i = new Generic<>() { // Why need type paramter here?
                                        ^
  reason: cannot use '<>' with anonymous inner classes
  where T is a type-variable:
    T extends Object declared in interface Generic
1 error

I cannot see where this is explicitly forbidden in the Java 8 edition of the JLS (but I might have missed it).我看不到在 JLS 的 Java 8 版本中明确禁止这样做的地方(但我可能错过了)。

In any case, this is permitted in Java 9 and later.无论如何,这在 Java 9 及更高版本中是允许的。 It was one of the changes made as part of Project Coin (JEP 213) :这是作为Project Coin (JEP 213)的一部分所做的更改之一:

"3. Allow diamond with anonymous classes if the argument type of the inferred type is denotable. Because the inferred type using diamond with an anonymous class constructor could be outside of the set of types supported by the signature attribute, using diamond with anonymous classes was disallowed in Java SE 7. As noted in the JSR 334 proposed final draft, it would be possible to ease this restriction if the inferred type was denotable." "3. 如果推断类型的参数类型是可表示的,则允许使用匿名类的菱形。因为使用带有匿名类构造函数的菱形的推断类型可能超出签名属性支持的类型集,所以使用带有匿名类的菱形是Java SE 7 中不允许。如 JSR 334 提议的最终草案中所述,如果推断的类型是可表示的,则可以放宽此限制。

This improvement was delivered in Java 9 .这个改进是在 Java 9 中提供的


What is the reason?是什么原因?

The technical reason is given in the quoted text above.技术原因在上面引用的文本中给出。

因为您有一个方法 f() 需要重载泛型类型。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM