&#34; <t extends =“”... =“”>&#34;意外的编译器警告返回类型</t>

时间:2014-12-30 16:06:49

标签: 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()

我无法理解为什么它会说&#34;返回类型需要未经检查的转换&#34;因为类实现Example所以我认为它是一个有效的返回类型。

任何人都可以向我解释什么是错的吗?

2 个答案:

答案 0 :(得分:3)

Example中的通用方法应该适用于T可以是任何类型Example,但您尝试以ExampleImpl方式实现它它始终返回ExampleImpl。如果ExampleImpl是唯一实现Example的类,则可能没问题,但如果有其他类,则可以在运行时获得ClassCastException

在下面的示例中,我们实例化一个新的ExampleImpl,将其强制转换为基接口,然后调用泛型方法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();
    }
}

答案 1 :(得分:2)

我的java有点生疏,但你不能在重写方法中返回派生类吗?

公共类StackOverflowQuestion {

interface Example {

    Example init();
}

static class ExampleImpl implements Example {

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

}