Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我必须强制转换为泛型类型T,即使我知道它返回正确?_Java_Generics - Fatal编程技术网

Java 为什么我必须强制转换为泛型类型T,即使我知道它返回正确?

Java 为什么我必须强制转换为泛型类型T,即使我知道它返回正确?,java,generics,Java,Generics,我的代码: private static <T> T get(Class<T> clazz) throws IllegalAccessException, InstantiationException { if (clazz.equals(String.class)) { return (T) new String("abc");//line x } else { return clazz.n

我的代码:

private static <T> T get(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        if (clazz.equals(String.class)) {
            return (T) new String("abc");//line x
        } else {
            return clazz.newInstance();
        }

    }
private static T get(Class clazz)抛出IllegaccessException、InstanceionException{
if(clazz.equals(String.class)){
返回(T)新字符串(“abc”);//第x行
}否则{
返回clazz.newInstance();
}
}
如您所见,在
行x
中,
T
必须是
String.class
并返回
String
。但是编译失败,没有将结果强制转换为
T


行x
更改为
返回新字符串(“abc”)结果
不兼容类型

编译器不考虑
if
语句

因此,它所看到的是,您需要返回一个
T
(它对此没有进一步的了解)。它没有推断这里的
T
必须是
String

通过执行以下操作,可以避免出现“未选中强制转换为已擦除类型”的警告


原因是您不能为每个类强制转换字符串。假设T是一个数字类,你会抛出一个ClassCastException

您可以尝试以下方法来解决问题:

return (T) ((Object) new String("abc"));

您可以按如下方式避免强制转换:

if (clazz.equals(String.class)) {
    return clazz.getDeclaredConstructor(String.class).newInstance("abc");
}
return clazz.newInstance();

您必须捕获(并忽略)一些异常。

这并不是模板的真正用途。当然,对您来说很明显,它总是返回类型为T的内容-但是对编译器来说这是显而易见的吗?如果T不是字符串,则仍有一些路径(可访问或不可访问)返回错误的类型。这不会产生相同的结果。OP的代码每次都创建一个新的字符串实例,但您的代码每次都返回相同的(插入的)字符串。可能
clazz.cast(新字符串(“abc”)还应注意,调用cast()仍然涉及不安全的强制转换,但它隐藏在cast方法中。@Bohemian:我悄悄地自动更正了
新字符串()
部分。在大多数情况下,您不需要新的字符串实例。
cast
在这里并不是不安全的,因为
if
语句已经检查了类型兼容性(这是这个问题的重点,我认为其他一些语言有更强的类型推断,考虑到了这种条件)。对不起,“不安全”从实际的角度来看并不是指不安全,而是编译器认为它不安全并生成警告。具体来说,
cast()
方法不返回(T)obj并用
@SuppressWarnings(“unchecked”)
-调用
cast()
只是将警告从代码中推到JDK中(我对此很酷-我自己经常使用这种模式)。我想说的(以及OP显然期望的)这可能被认为是编译器的一个缺点,它认为原始代码中的强制转换不安全,并生成警告。在一个条件块内部,比如问题中的代码中,强制转换永远不会失败。有些系统确实支持这种推断。以Eclipse为例,它将在
中的狭窄类型上自动完成方法,如果(某物的x实例){
(并自动插入编译器所需的强制转换)。@Bohemian:通过使用
cast()
,您可以“隐藏”未经检查的强制转换,这样您就不会再看到警告,但它同样不安全。但事实并非如此。Java标准库API永远不会允许您在没有警告的情况下执行不安全的操作(其中不安全包括堆污染之类的内容)。什么
cast()
的内部代码并不重要——重要的是它的API——它的API不允许您使用它造成堆污染,而未经检查的强制转换是不安全的,因为它可能导致堆污染。
if (clazz.equals(String.class)) {
    return clazz.getDeclaredConstructor(String.class).newInstance("abc");
}
return clazz.newInstance();