Java从方法返回类型派生的泛型类型推断

时间:2012-01-19 20:41:01

标签: java generics javac type-inference eclipse-jdt

public class TestCase {
    public static String compiles() {
        return getAction();
    }

    /*
    public static String doesntCompile1() {
        return (String) getAction();
    }

    public static String doesntCompile2() {
        return TestCase.<String> getAction();
    }
    */

    public static <T extends javax.swing.Action> T getAction() {
        return (T) null;
    }
}

这应该被视为javac v1.6.0_22和jdt v3.7.1中的错误吗?对我来说似乎是这样,因为在其他情况下,编译器实际上发现了潜在的ClassCastException。在compiles方法中,这将在运行时抛出ClassCastException。

带来此示例的原始代码未在javac中编译,打印以下异常。不幸的是,我出于某种原因提供的例程代码不会产生此错误。

type parameters of <T>T cannot be determined;
no unique maximal instance exists for type variable T with upper bounds

2 个答案:

答案 0 :(得分:3)

我希望一个好的编译器能够检测错误,但作为优化。您提出了一个更为一般的案例的具体案例:

public class TestCase {
    public static TypeA methodA() {
        return methodB();
    }

    public static <T extends TypeB> T methodB() {
        return (T) null;
    }
}

现在,一般来说,没有任何问题,提供:

  1. 如果TypeA和TypeB都是类,则TypeB是TypeA的超类。
  2. TypeA 或TypeA的某个子类型继承自TypeB。
  3. 现在,编译器检查的关键是#2,在这种情况下它可以。但那只是 ,因为String是最终类。如果该类不是final,则#2将始终为true,因为在编译时不知道潜在的子类。

    想象一下,您使用String而不是CharSequence。然后我希望这三个人都能编译。但是,我无法解释为什么在您的示例中第二个和第三个方法不能编译。

    修改

    现在我已经用javac尝试了它,并且发现第一个方法也没有编译。以上接受了你的问题的前提似乎是错误的。我得到了误导性的编译错误

      

    不兼容的类型。必填:java.lang.String。找到:T

    这个答案没有回答完整的问题,而是解释了为什么它不起作用,但是这样的事情:

    public static CharSequence compiles() {
        return (CharSequence)getAction();
    }
    

    确实

答案 1 :(得分:-1)

我不明白这里的问题是什么。你得到的错误既明显又可预期。

对于doesntCompile1方法,我的编译器告诉我

  

无法从Action转换为String

这完全是预期的 - 我们知道该方法返回T Action,我们知道Action无法转换为String。< / p>

对于doesntCompile2方法,我的编译器告诉我

  

绑定不匹配:类型TestCase的泛型方法getAction()不适用于arguments()。推断类型String不是有界参数

的有效替代

基本上与上述原因相同

你期望它做什么?