哪个更好,更便宜:类匹配与异常?

时间:2009-11-20 07:04:50

标签: c# java exception

哪个更便宜,更可取: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 (...){}

5 个答案:

答案 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(其中 检查条件,而不是错误...)

如果您正在编写代码,那么从不关心性能!