这行代码
Class<String> cls = (Class<String>) Class.forName("java.lang.String");
给出编译器警告Type safety: Unchecked cast from Class<capture#1-of ?> to Class<String>
此外,根据API定义,它返回返回Class<?>
:
Class<?> Class.forName(String arg)
我不明白为什么将从Class<?>
到Class<String>
的转换视为未选中(也就是说,编译器无法检查在编译时是否可以进行这种转换)。
如果是
Class<String> cls = (Class<String>) Class.forName("some_str_var");
我可以理解,编译器在编译时无法知道Class.forName()的返回类型(因为参数是变量,而不是文字),并且在运行时会擦除类型信息。
但是Class.forName("java.lang.String")
在编译过程中明显Class<?>
(并且LHS中的cls
变量仍然是Class<String>
),还没有擦除任何类型信息(编译器看到的是源代码,不是字节代码并删除了type-info),编译器可以检查所有内容。
答案 0 :(得分:5)
在此调用中,编译器未对字符串常量...
[02:05:55:833] com.gluonhq.higgs.Compiler: halfway done round 14
[02:05:56:201] com.gluonhq.higgs.Compiler: done round 14
[02:05:56:201] com.gluonhq.higgs.Compiler: Waiting for remaing classes to be compiled on executor
[02:05:56:202] com.gluonhq.higgs.Compiler: active count = 0 and coresize = 2 and queuesize = 0
[02:05:56:202] com.gluonhq.higgs.Compiler: shutdown executor
[02:05:56:202] com.gluonhq.higgs.Compiler: shutdown executor done
[02:05:56:202] com.gluonhq.higgs.Compiler: await term done
[02:05:56:202] com.gluonhq.higgs.Compiler: All classes are now compiled
[02:05:56:202] com.gluonhq.higgs.Compiler: Compiled 0 classes in 25.835 seconds
[02:05:56:224] com.gluonhq.higgs.Higgs: non-fatal issue for class com.gluonhq.impl.charm.a.b.b.f (no known superclass)
[02:05:56:225] com.gluonhq.higgs.Higgs: non-fatal issue for class com.gluonhq.impl.charm.a.b.b.m (no known superclass)
[02:05:56:226] com.gluonhq.higgs.Higgs: non-fatal issue for class com.gluonhq.impl.charm.a.b.b.o (no known superclass)
[02:05:56:226] com.gluonhq.higgs.Higgs: non-fatal issue for class com.gluonhq.impl.charm.a.b.b.v (no known superclass)
[02:05:56:232] com.gluonhq.higgs.Higgs: ERROR for class com.sun.javafx.property.adapter.PropertyDescriptor$Listener
[02:05:56:233] com.gluonhq.higgs.Higgs: ERROR for class com.sun.javafx.property.adapter.ReadOnlyPropertyDescriptor$ReadOnlyListener
[02:05:56:263] com.gluonhq.higgs.Higgs: non-fatal issue for class javafx.scene.web.JSObjectIosImpl (no known superclass)
[02:05:56:267] com.gluonhq.higgs.Higgs: non-fatal issue for class net.miginfocom.layout.BoundSize$1 (no known superclass)
[02:05:56:268] com.gluonhq.higgs.Higgs: ERROR for class net.miginfocom.layout.LayoutUtil$1
[02:05:56:269] com.gluonhq.higgs.Higgs: non-fatal issue for class net.miginfocom.layout.UnitValue$1 (no known superclass)
ERR: Launch simulator on simudid: B3D4F644-FC5F-4DBE-8586-9C3D0D6E4E70 and launchDir = /Users/user/Documents/tesla/teslaApp/build/gvm/teslaApp.app
[SUB] Failed to install application. Error Domain=IXUserPresentableErrorDomain Code=1 "This app could not be installed at this time." UserInfo={NSLocalizedFailureReason=Failed to chmod /Users/user/Library/Developer/CoreSimulator/Devices/B3D4F644-FC5F-4DBE-8586-9C3D0D6E4E70/data/Bundle/Application/4C023753-2AC3-42BC-95E9-C46FCF4996D6/teslaApp.app/TeslaTasks : No such file or directory, NSUnderlyingError=0x7fdf2cf19870 {Error Domain=MIInstallerErrorDomain Code=4 "Failed to chmod /Users/user/Library/Developer/CoreSimulator/Devices/B3D4F644-FC5F-4DBE-8586-9C3D0D6E4E70/data/Bundle/Application/4C023753-2AC3-42BC-95E9-C46FCF4996D6/teslaApp.app/TeslaTasks : No such file or directory" UserInfo={NSLocalizedDescription=Failed to chmod /Users/user/Library/Developer/CoreSimulator/Devices/B3D4F644-FC5F-4DBE-8586-9C3D0D6E4E70/data/Bundle/Application/4C023753-2AC3-42BC-95E9-C46FCF4996D6/teslaApp.app/TeslaTasks : No such file or directory, LegacyErrorString=ExecutableTwiddleFailed, FunctionName=-[MIExecutableBundle makeExecutableWithError:], SourceFileLine=1221, NSUnderlyingError=0x7fdf2cf1b180 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}}, NSLocalizedRecoverySuggestion=Failed to chmod /Users/user/Library/Developer/CoreSimulator/Devices/B3D4F644-FC5F-4DBE-8586-9C3D0D6E4E70/data/Bundle/Application/4C023753-2AC3-42BC-95E9-C46FCF4996D6/teslaApp.app/TeslaTasks : No such file or directory, NSLocalizedDescription=This app could not be installed at this time.}
进行任何特殊处理:
"java.lang.String"
Class.forName("java.lang.String")
只是众多方法之一,就像传递给它的参数只是众多字符串之一一样。
因此以下两个对于编译器是相同的(就返回类型而言):
Class.forName
和
String className = "java.lang.String";
Class<String> stringClass = Class.forName(className);
编译器不会检查常量参数来推断它必然是Class<String> stringClass = Class.forName("java.lang.String");
。如果要以类型安全的方式获取Class<String>
,则必须使用:
Class<String>
答案 1 :(得分:1)
由字符串"java.lang.String"
表示的类恰好在编译时可用,因为它是标准库的一部分。因此,编译器原则上可以执行class.forName()
并检查返回的类是否与类型声明匹配。
但这将是特例。通常,该字符串可能会指定一个在编译时根本不可用的类-例如,它可能在可运行时动态加载的可插入库中。
因此,编译器仅采用最简单,最通用的方法。编译器很复杂,设计人员通常选择不增加更多的复杂性,而只会增加一些特殊情况。
我还怀疑自定义类加载器的可能性可能会使实现此检查变得困难。即使在标准库中,编译时可用的类也可能没有保证(由Java语言规范保证)在运行时可用,即使对于标准库也是如此-即使它们通常是 一样。