Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java.util.AbstractMap.equals():try/catch的作用是什么?_Java_Exception Handling - Fatal编程技术网

java.util.AbstractMap.equals():try/catch的作用是什么?

java.util.AbstractMap.equals():try/catch的作用是什么?,java,exception-handling,Java,Exception Handling,在编写自己的自定义MultiHashMap、multiTreeMap等类时(是的,我知道这些类在Guava Library中可用,但我需要提供一些不同的功能,因此我从头开始完全重写了这些类),我遇到了编写一个equals()方法的需要,该方法可以比较任何MultiMap,当且仅当两个多重映射的入口集相等(相同的键值映射,无论顺序如何)时返回true 当我在一个普通映射中保存多个值时,我将自己的方法与API方法java.util.AbstractMap.equals()进行了比较,结果发现它们非常

在编写自己的自定义MultiHashMap、multiTreeMap等类时(是的,我知道这些类在Guava Library中可用,但我需要提供一些不同的功能,因此我从头开始完全重写了这些类),我遇到了编写一个equals()方法的需要,该方法可以比较任何MultiMap,当且仅当两个多重映射的入口集相等(相同的键值映射,无论顺序如何)时返回true

当我在一个普通映射中保存多个值时,我将自己的方法与API方法java.util.AbstractMap.equals()进行了比较,结果发现它们非常相似,只是我没有使用任何try/catch(java 7):

公共布尔等于(对象o){
如果(o==这个)
返回true;
如果(!(映射的实例))
返回false;
Map m=(Map)o;
如果(m.size()!=size())
返回false;
试一试{
迭代器i=entrySet().Iterator();
while(i.hasNext()){
条目e=i.next();
K key=e.getKey();
V value=e.getValue();
如果(值==null){
if(!(m.get(key)==null&&m.containsKey(key)))
返回false;
}否则{
如果(!value.equals(m.get(key)))
返回false;
}
}
}捕获(ClassCastException未使用){
返回false;
}捕获(NullPointerException未使用){
返回false;
}
返回true;
}
捕获到的异常是RuntimeException的异常,除此之外,我真的不知道它们在什么情况下会发生


有什么提示吗?

我想,catch是用来捕获
V
类型中
equals
方法的错误实现。调用
value.equals(m.get(key))
可能会抛出
ClassCastException
和或
NullPointException
,而
equals
是在
V
中简单实现的

在实际的
V
参数类型中,
等于
的错误实现,可以很好地捕捉到:

class Whatever {
  private int attr;
  /* ... */
  @Override public boolean equals(Object o) {
    Whatever w= (Whatever)o; // possible ClassCastException
    return (this.attr == w.attr); // possible NullPointerException
  }
}

它们使用捕获异常来缩短
equals()
代码。我不认为这是一个好的做法,但它的工作。它们通过捕获异常来替换许多
if
-检查

请看一个Eclipse自动生成的
equals()
方法的示例:

public class Person {
    final private String firstName;
    final private String lastName;
    ...
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Person other = (Person) obj;
        if (firstName == null) {
            if (other.firstName != null) {
                return false;
            }
        }
        else if (!firstName.equals(other.firstName)) {
            return false;
        }
        if (lastName == null) {
            if (other.lastName != null) {
                return false;
            }
        }
        else if (!lastName.equals(other.lastName)) {
            return false;
        }
        return true;
    }
}
这是实现
equals()
的正确方法。 现在请注意,在所有情况下,当针对正确类型或null的测试失败时,
equals()
方法返回
false
。因此,您提供的代码中的想法是对所有检查进行ommit,并捕获异常。大概是这样的:

@Override
public boolean equals(Object obj) {
    try {
        // Ommit any type-checks before type-casting
        // and replace them with catching ClassCastException:
        final Person other = (Person) obj;
        // Ommit any null-checks before using the references
        // and replace them with catching NullPointerException:
        if (firstName.equals(other.firstName)
                && lastName.equals(other.lastName)) {
            return true;
        }
    }
    catch (ClassCastException | NullPointerException unused) {
        // swallow the exception as it is not an error here
    }
    return false;
}
正如您所看到的,代码也做了同样的事情,但要短得多。然而,这通常被认为是不好的做法。但我必须承认,代码的可读性更好:)

Joshua Bloch的第57项:仅在例外情况下使用例外,这一点被认为是不好的做法的原因已经非常清楚了:

例外情况,顾名思义,仅用于例外情况 条件不得将其用于普通控制流


答案似乎很简单:因为
Map.containsKey
方法可能会抛出这两个异常

从地图界面的文档中:

/**
 * ....
 * @throws ClassCastException if the key is of an inappropriate type for
 *         this map (optional)
 * @throws NullPointerException if the specified key is null and this map
 *         does not permit null keys (optional)
 */
boolean containsKey(Object key);

尽管
AbstractMap
中的containsKey实现实际上并没有抛出这些异常,但一些自定义实现最终可能会抛出这些异常。处理这些异常最可靠的方法是在try-catch块中包装
containsKey

另外:它被认为是坏习惯的一个原因是,你必须知道它是一个较短的形式。。。否则会导致问题,这一点可以证明;-)
/**
 * ....
 * @throws ClassCastException if the key is of an inappropriate type for
 *         this map (optional)
 * @throws NullPointerException if the specified key is null and this map
 *         does not permit null keys (optional)
 */
boolean containsKey(Object key);