Ale*_*poy 7 java generics variadic-functions overload-resolution java-8
我正在尝试将Java 7代码迁移到Java 8,所以我的代码类似于:
package tests;
import java.util.Arrays;
import java.util.Map;
public class Tests {
private static interface ComparableMap<K,V> extends Map<K,V>, Comparable {}
public static void main(String[] args) {
func(getString());
}
private static void func(Comparable...input){
System.out.println(Arrays.toString(input));
}
private static void func(ComparableMap <?,?> m){
System.out.println(m);
}
private static <T extends Comparable> T getString(){
return (T) "aaa";
}
}
Run Code Online (Sandbox Code Playgroud)
在java 7中它正常工作,在Java 8中我得到:
java.lang.ClassCastException:java.lang.String无法强制转换为tests.Tests $ ComparableMap
如果我将一个函数定义更改为:
private static <T> T getString(){
return (T) "aaa";
}
Run Code Online (Sandbox Code Playgroud)
编译将失败:错误:
对func的引用含糊不清
为什么Java 8编译器在第一种情况下没有失败?(看起来对我来说是错误的)是否可以更改第二个重载函数,以便在不更改调用本身的情况下使用varargs参数调用第一个函数?
在第一种情况下,该方法getString
需要返回一个Comparable
实例.编译器查找该func
方法的重载,并且只找到一个可以接受的方法Comparable
:func(Comparable ... input)
.Map
没有实现该接口,因此第二个重载不适用.没有含糊之处.
在第二种情况下,getString
可以返回任何东西.这两个重载都有效,因此存在歧义.但请注意,在两种情况下,对T的强制转换都是不安全/错误的.
你编写的泛型方法基本上告诉编译器"我可以返回你想要实现的任何类的实例Comparable
".但你实际上不能遵守这个承诺.
可以说我有以下代码:
String str = getString();
Integer num = getString();
Run Code Online (Sandbox Code Playgroud)
这段代码将编译,String
并Integer
实现Comparable
接口.第二行将在运行时失败:代码尝试将a String
转换为Integer
.
你的第二个案例也是错误的,原因与我上面解释的相同.它承诺它可以返回任何你想要的类型.它似乎也不能保持这个承诺(Runnable
这是一个随机的例子,它可以是任何东西):
Runnable run = getString()
Run Code Online (Sandbox Code Playgroud)
编译器看到两个匹配的可能重载,func(Comparable...input)
和func(ComparableMap <?,?> m)
.它更喜欢第二个,因为varargs方法总是最后选择(出于竞争性原因).所有这些都是核心行为.
然后代码抛出ClassCastException,因为你的getString
方法没有保证它的承诺(让调用者决定Comparable
返回什么样的类型).
根本问题是你的getString
方法做出了错误的承诺.因此,我真的不知道该代码试图完成什么.如果你能详细说明,我们可以帮助你进一步发展.
归档时间: |
|
查看次数: |
259 次 |
最近记录: |