Mik*_*aig 17 java generics polymorphism
假设你有一个方法
它看起来像这样:
<N extends Number & Comparable<N>, S extends N> S ensureLessThan(N threshold, S input) {
if (input.compareTo(threshold) >= 0) {
throw new IllegalArgumentException("Input " + input + " is not less than " + threshold);
}
return input;
}
Run Code Online (Sandbox Code Playgroud)
运行时,此方法抛出NoSuchMethodError:
Exception in thread "main" java.lang.NoSuchMethodError: java.lang.Number.compareTo(Ljava/lang/Object;)I
Run Code Online (Sandbox Code Playgroud)
添加看起来像冗余演员的东西使它工作:
...
if (((N) input).compareTo(threshold) >= 0) {
...
Run Code Online (Sandbox Code Playgroud)
那么这里发生了什么?
更新:我的Java版本是
java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-11M3909)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
Run Code Online (Sandbox Code Playgroud)
这是一个可运行的例子:https://gist.github.com/4526536
我怀疑这是编译器中的一个错误.它Number.compareTo(Object)应该是静态绑定的,不存在Comparable.compareTo(Object).
if (threshold.compareTo(input) < 0) {
Run Code Online (Sandbox Code Playgroud)
将工作.
它当然似乎是编译器错误.这样做的原因是编译器生成一个已检查的强制转换为Comparable.而另一种方式却没有.
ensureLessThan(Ljava/lang/Number;Ljava/lang/Number;)Ljava/lang/Number;
L0
LINENUMBER 11 L0
ALOAD 1
CHECKCAST java/lang/Comparable
ALOAD 2
INVOKEINTERFACE java/lang/Comparable.compareTo (Ljava/lang/Object;)I
IFGE L1
Run Code Online (Sandbox Code Playgroud)
与
ensureLessThan(Ljava/lang/Number;Ljava/lang/Number;)Ljava/lang/Number;
LINENUMBER 11 L0
ALOAD 1
ALOAD 2
INVOKEVIRTUAL java/lang/Number.compareTo (Ljava/lang/Object;)I
IFGE L1
Run Code Online (Sandbox Code Playgroud)