我看到编译器允许以下方法。但是谁能解释在编译时如何确定返回类型,以及T的值是什么。 您还可以给我参考文档或视频,以便我进一步了解Java编译器将如何在内部确定泛型类型。
public <T> T getValue(String abc) throws Exception {
if(abc.equals("x")){
return (T) new String[]{"x","y","z"};
} else {
return (T) "abc";
}
}
答案 0 :(得分:2)
在编译时有类型擦除过程。来自javadoc:
在类型擦除过程中,Java编译器将擦除所有类型参数,如果类型参数是有界的,则将每个参数替换为其第一个边界;如果类型参数是无界的,则将其替换为对象
因此,在您的示例中,所有T
都将替换为Object
类型。但是在执行期间,它将强制转换为您指定的类型。例如:
Integer value = obj.<Integer>getValue("string");
没有编译时错误,但是在运行时它将尝试应用强制转换return (Integer) "abc";
,您将获得ClassCastException
答案 1 :(得分:0)
您不能一般地这样做。
最好的办法是使用非泛型方法,返回一个公共超类-在这种情况下,为Object
:
public Object getValue(String abc) throws Exception {
if(abc.equals("x")){
return new String[]{"x","y","z"};
} else {
return "abc";
}
}
这使调用者承担了将对象转换为适当类型的负担,您可以避免这种情况。但是请注意,您当前的方法也可以这样做,因为没有什么可以阻止他们编写此代码:
String s = getValue("x");
String[] arr = getValue("x");
这两个都很好,但是其中之一将在运行时失败。调用者必须以某种方式知道哪些调用将返回String
,哪些调用将返回String[]
。
强制他们进行投射的优势在于,他们可以看到投射,并知道他们将必须保重。
更好的方法是在所有情况下都返回相同类型的值:改为返回new String[]{"abc"}
。