我最近在编写程序时遇到了一个异常,我花了很多时间来调试,仅仅是因为我被编译器给了错误的异常。
这是我的活动代码:
private var mCheatMap = HashMap<Int, Boolean>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz)
mCheatMap = savedInstanceState?.getSerializable(KEY_CHEATER) as HashMap<Int, Boolean> ?: HashMap<Int, Boolean>()
}
在运行时,我的应用程序崩溃了,当我查看日志时,它说ActivityNotFound
异常,并且在建议中,它说也许我没有在我的AndroidManifest.xml
中声明活动
从我身边看,一切似乎都没有出错,突然间,我偶然地将我的mCheapMap
变量铸件变成了安全的铸件,一切都开始完美地工作。 例如:
private var mCheatMap = HashMap<Int, Boolean>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz)
mCheatMap = savedInstanceState?.getSerializable(KEY_CHEATER) as? HashMap<Int, Boolean> ?: HashMap<Int, Boolean>()
}
现在我有一些困惑:
为什么编译器在我遇到转换问题时给了我
ActivityNotFound
异常?
为什么使用安全铸造操作员可以解决问题,因为即使没有安全铸造操作员,我的铸造也是正确的?
在运行时,如果问题是关于错误的转换,你应该得到一个ClassCastException
(顺便说一下,抛出异常的不是编译器,而是运行时。不过,编译器/LINT 应该警告您"未经检查的强制转换"(。
关于你的第二个问题,如果投射不成功,安全强制转换将返回null
,这使您落入猫王运算符 (?:
( 的"else"分支,因此您将创建一个新的空HashMap<Int, Boolean>
并将其分配给您的mCheatMap
变量。这在您的第一个示例中不会发生,因为失败的强制转换会抛出异常而不是简单地返回null
,因此 elvis 运算符的"else"分支永远无法执行(您应该为此收到编译器/LINT 的另一个警告(。