java - "<T extends ...>"返回类型的意外编译器警告

标签 java generics javac

当我编译以下 Java 代码时(使用 Oracle JDK 1.7.0_25):

public class StackOverflowQuestion {

    interface Example {

        <T extends Example> T init();
    }

    static class ExampleImpl implements Example {

        @Override
        public ExampleImpl init() {
            return this;
        }
    }
}

我收到警告:

StackOverflowQuestion.java:11: warning: [unchecked] init()
  in ExampleImpl implements <T>init() in Example
        public ExampleImpl init() {
                           ^
  return type requires unchecked conversion from ExampleImpl to T
  where T is a type-variable:
    T extends Example declared in method <T>init()

我不明白为什么它说“返回类型需要未经检查的转换”,因为该类实现了 Example,据我所知,它是一个有效的返回类型。

谁能给我解释一下这是怎么回事?

最佳答案

Example中的泛型方法应该在哪里工作 T可以是扩展 Example 的任何类型, 但您已尝试在 ExampleImpl 中实现它以这样一种方式,它总是返回一个 ExampleImpl .这可能没问题,如果 ExampleImpl是唯一实现 Example 的类, 但如果还有其他人,您可以获得 ClassCastException在运行时。

在下面的例子中,我们实例化了一个新的 ExampleImpl ,将其转换为基接口(interface),然后调用泛型方法 init()T等于ExampleImpl2 .这应该返回 ExampleImpl2 , 但自从你返回 this , 它会抛出 ClassCastException .这就是您的代码必须生成警告的原因。

public class StackOverflowQuestion {

    interface Example {

        <T extends Example> T init();
    }

    static class ExampleImpl implements Example {

        @Override
        public ExampleImpl init() {
            return this;
        }
    }

    static class ExampleImpl2 implements Example {

        @Override
        public <T extends Example> T init() {
            return null;
        }
    }

    public static void main(String[] args) {
        ExampleImpl2 e2 = ((Example) new ExampleImpl()).<ExampleImpl2>init();
    }
}

关于java - "<T extends ...>"返回类型的意外编译器警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27708667/

相关文章:

用于 XLSX 文件扩展名的 Java 正则表达式

java - 如何安装 Xuggler?

Java 泛型类,如何为可能的参数类型定义构造函数

c# - ToString() 没有返回预期的字符串

java - 如何在导出到 jar 时分离 eclipse 中的 .java 文件

java - 在哪里可以找到 Java 8 版本的 JVM 规范?

java - Java 内存中的动态编译类以及依赖于这些类的类

java - 如何修复NoSuchMethodError:org.apache.hadoop.mapred.InputSplit.write

Java EDT 和生成对话

linq - 动态地将类型传递给方法<T>