Java 未经检查的强制转换行为(有或无变量赋值)
为什么main中的第一行不抛出ClassCastException,而第二行抛出ClassCastExceptionJava 未经检查的强制转换行为(有或无变量赋值),java,generics,unchecked-exception,Java,Generics,Unchecked Exception,为什么main中的第一行不抛出ClassCastException,而第二行抛出ClassCastException import java.util.function.Function; class Scratch { static <T> T getSomething(Function<Integer, T> fun) { return (T) fun; } public static void main(String[]
import java.util.function.Function;
class Scratch {
static <T> T getSomething(Function<Integer, T> fun) {
return (T) fun;
}
public static void main(String[] args) {
Scratch.<String>getSomething(x -> "hello");
String something = Scratch.<String>getSomething(x -> "hello");
}
}
import java.util.function.function;
课堂擦伤{
静态T getSomething(函数乐趣){
返回(T)乐趣;
}
公共静态void main(字符串[]args){
Scratch.getSomething(x->“hello”);
stringsomething=Scratch.getSomething(x->“hello”);
}
}
泛型只是一种编译时检查(请阅读)。因此,在运行时,您的getSomething()
方法与此类似:
static Object getSomething(Function fun) {
return fun;
}
String something = (String) Scratch.getSomething(x -> "hello");
现在您清楚地看到,第一行永远不会抛出异常
Scratch.getSomething(x -> "hello");
因为函数
是对象
,因此可以毫无问题地返回
但是,第二行将抛出一个,因为它看起来类似于:
static Object getSomething(Function fun) {
return fun;
}
String something = (String) Scratch.getSomething(x -> "hello");
函数
仍然是一个对象
,因此可以从方法返回它,但它不是字符串
,因此,您可以得到类异常
代码编译得很好,因为您指示编译器您知道自己在做什么。您将得到一个未选中的cast
警告,尽管在这一行:
return (T) fun;
此警告应该是编译器向您(程序员)发出的一个指示,表明它(编译器)无法确保强制转换将成功。区别在于,在第一种情况下,您不使用方法的结果,但在第二种情况下使用 强制转换是一个表达式,但它不是一个
语句表达式
。这意味着您不能编写以下内容:
(String) somethingReturningAString();
但你可以写:
String aString = (String) somethingReturningAString();
在编译时,编译器会在需要的地方以及可以插入的地方插入checkcast
指令:
- 它无法为第一个案例插入类型转换,因此不会进行检查
- 它可以(而且必须)在第二种情况下插入强制转换,以确保它将实际是
字符串的内容分配给
字符串
变量。因此,它会检查演员阵容,但失败了
值得注意的是,有些情况可能出乎意料,强制转换不是严格必需的,而是插入的。例如:
Scratch.<String>getSomething(x -> "hello").toString();
尽管
Object
有一个toString()
方法,因此它可以在没有强制转换的情况下调用该方法。无法回答这个问题,但显然您试图将函数强制转换为字符串,这不太可能工作。需要一个有趣的电话。在那里某处申请。因为你在第二种情况下使用结果,但在第一种情况下不使用。