哪个更便宜,更可取:put1或put2?
Map<String, Animal> map = new Map<String, Animal>();
void put1(){
for (.....)
if (Animal.class.isAssignableFrom(item[i].getClass())
map.put(key[i], item[i]);
void put2(){
for (.....)
try{
map.put(key[i], item[i]);}
catch (...){}
问题修订: 问题不是那么清楚。让我稍微修改一下这个问题。我忘记了转换,因此put2依赖于强制转换异常失败。 isAssignableFrom(),isInstanceOf()和instanceof在功能上相似,因此产生相同的费用,只有一个是包含子类的方法,而第二个是精确类型匹配,第三个是运算符版本。反射方法和例外都是昂贵的操作。
我的问题是那些在这个领域做过一些基准测试的人 - 哪个更便宜,更可取:例如/是否可以与强制转换异常进行对比?
void put1(){
for (.....)
if (Animal.class.isAssignableFrom(item[i].getClass())
map.put(key[i], (Animal)item[i]);
void put2(){
for (.....)
try{
map.put(key[i], (Animal)item[i]);}
catch (...){}
答案 0 :(得分:12)
可能你想要:
if (item[i] instanceof Animal)
map.put(key[i], (Animal) item[i]);
这几乎肯定比调用isAssignableFrom
要好得多。
或者在C#中(因为你添加了c#标签):
var a = item[i] as Animal;
if (a != null)
map[key[i]] = a;
编辑:更新后的问题更好:instanceof或cast-and-catch。功能基本相同。性能差异可能不大,我不得不衡量它;一般抛出异常很慢,但我不知道其余的。所以我会根据风格来决定。说出你的意思。
如果你总是希望期望item[i]
成为Animal
,那么你只需要特别小心,投射和捕获。否则我发现使用instanceof更清楚,因为它明确地说出了你的意思:“如果这个对象是动物,就把它放在地图中”。
答案 1 :(得分:2)
我很困惑。如果item[i]
不是Animal
,那么map.put(key[i], item[i])
如何编译?
那就是说,第一种方法说明了你打算做什么,虽然我相信instanceof
会更好一些。
答案 2 :(得分:1)
通常,异常处理会明显变慢,因为它应该被用于特殊事物(很少发生),因此VM制造商不会花费太多工作来加速它。
你的代码的tr / catch版本我认为是滥用异常处理而且永远不会考虑这样做。你想要做这样的事情的事实可能意味着你的设计很差,项目应该是Animal []而不是其他东西,在这种情况下你根本不需要在运行时检查。让编译器为您完成工作。
答案 3 :(得分:1)
我同意之前的回答 - 这不会编译。
但是,在我看来,无论是异常还是检查取决于功能的目的。
项目[i]不是动物错误/例外情况吗?预计很少发生吗?在这种情况下,它应该是一个例外。
如果它是逻辑的一部分 - 意味着你期望item [i]是很多东西 - 并且只有当你想要放入地图时它才是动物。在这种情况下,检查实例是正确的方法。
更新: 我还要添加一个例子(位跛):
哪个更好: (1)
if ( aNumber < 100 ) {
processNumber(aNumber);
}
或(2)
try {
processNumber(aNumber); //Throws exception if aNumber >= 100
} catch () {
}
这取决于程序的功能。 (1)可用于计数数字&lt; 100表示任何整数输入。如果processNumber期望一个不能大于100的百分比值,将使用(2)。
不同之处在于,程序(2)获取aNumber&gt;是错误的。 100.然而,对于程序(1)aNumber&gt; 100是有效的,但只有当aNumber <1时才会发生“某事”。 100.
PS - 这可能对你没有任何帮助,如果是这种情况我会道歉。
答案 4 :(得分:0)
你的两个选择并不是真的相同。选择哪一个,完全取决于您的代码应该做什么:
Animal
,然后你应该使用
put2
(如果
事实并非如此......)Animal
,您应该使用put1
(其中
检查条件,而不是错误...)如果您正在编写代码,那么从不关心性能!