考虑以下程序:
public class GenericTypeInference {
public static void main(String[] args) {
print(new SillyGenericWrapper().get());
}
private static void print(Object object) {
System.out.println("Object");
}
private static void print(String string) {
System.out.println("String");
}
public static class SillyGenericWrapper {
public <T> T get() {
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它在Java 8下打印"String",在Java 7下打印"Object".
我原以为这是Java 8中的歧义,因为两种重载方法都匹配.为什么编译器print(String)在JEP 101之后选择?
是否合理,这会破坏向后兼容性,并且在编译时无法检测到更改.升级到Java 8后,代码只是偷偷摸摸地表现不同.
注意:由于SillyGenericWrapper某种原因,它被命名为"愚蠢".我试图理解为什么编译器的行为方式,不要告诉我这个愚蠢的包装器首先是一个糟糕的设计.
更新:我还尝试在Java 8下编译和运行示例,但使用的是Java 7语言级别.这种行为与Java 7一致.这是预期的,但我仍然觉得需要验证.
public class Primitive {
void m(Number b, Number ... a) {} // widening, autoboxing->widening->varargs
void m(byte b, Number ... a) {} // unboxing, autoboxing->widening->varargs
public static void main(String[] args) {
Byte b = 12;
Primitive obj = new Primitive();
obj.m(b, 23);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经搜索过并发现扩展优先级高于取消装箱,因此在上面的方法调用中,应该调用第一个方法,因为第二个参数对于两者都是相同的.但这不会发生.你可以解释一下吗?
我不明白为什么在这里的情况1,它没有给出编译错误,相反在情况2(varargs),它给出了编译错误.任何人都可以详细说明编译器在这两种情况下的差异吗?我经历过很多关于它的帖子,但还不能理解它.
情况1
public class Test {
public void display(int a) {
System.out.println("1");
}
public void display(Integer a) {
System.out.println("2");
}
public static void main(String[] args) {
new Test().display(0);
}
}
Run Code Online (Sandbox Code Playgroud)
输出为: 1
案例#2
public class Test {
public void display(int... a) {
System.out.println("1");
}
public void display(Integer... a) {
System.out.println("2");
}
public static void main(String[] args) {
new Test().display(0);
}
}
Run Code Online (Sandbox Code Playgroud)
编译错误:
The method display(int[]) is ambiguous for the type Test
Run Code Online (Sandbox Code Playgroud) 有人可以帮助解释为什么测试 2 和测试 3 有问题吗?
public static void main (String[] args) {
byte b = 5;
doCalc(b, b);
}
Run Code Online (Sandbox Code Playgroud)
测试1:这两种方法没有歧义问题。
static void doCalc(byte a, byte b) {
System.out.print("byte, byte");
}
static void doCalc(Byte s1, Byte s2) {
System.out.print("Byte, Byte");
}
Run Code Online (Sandbox Code Playgroud)
测试2:这两个方法没有编译时二义性,但存在运行时二义性。
static void doCalc(Byte... a) {
System.out.print("byte 1...");
}
static void doCalc(long... a) {
System.out.print("byte 2...");
}
Run Code Online (Sandbox Code Playgroud)
测试3:这两个方法在编译时存在二义性。
static void doCalc(Byte... a) {
System.out.print("byte 1...");
}
static void doCalc(byte... a) {
System.out.print("byte 2...");
}
Run Code Online (Sandbox Code Playgroud)