检查防御性副本的空值的首选方法

时间:2011-09-12 16:53:50

标签: java

假设我有以下方法:

public void change(Map<String, String> map)

如果mapnull,我想抛出异常,如果不是,则提出防御性副本。

这会是首选:

public void change(Map<String, String> map)
{
    Map<String, String> temp = null;

    synchronized (map) {
            if (map == null)
                throw new NullPointerException("map is null");
        temp = new HashMap<String, Object>(map);
}

public void change(Map<String, String> map)
    try {
        Map<String, String> temp = new HashMap<String, Object>(map);
    } 
    catch (NullPointerException e) {
        throw new NullPointerException("map is null");
    }

还是有更好的方法?为什么以及为什么不呢。

编辑

修改了我的一些拼写错误:

properties应为map

(String,Object)应为(String, String)

谢谢!

5 个答案:

答案 0 :(得分:5)

如果map为空而不是由于您的代码,而是由于synchronized阻止,那么您的第一种方式会抛出异常。

鉴于您在第二种方法中声明了一个本地变量,这并不是很清楚你要做什么,这将是毫无意义的。想法是设置实例变量,还是在创建副本后在地图上执行更多工作?

您还需要知道在线程方面会发生什么 - 您不能保证一切都将在地图引用本身上同步。就个人而言,我会将线程与其他问题隔离开来,并更集中地处理它。我写这样的东西,使用Guava进行两次调用:

public void change(Map<String, String> map)
{
    Preconditions.checkNotNull(map);
    Map<String, String> copy = Maps.newHashMap(map);
    // Use copy here
}

Maps.newHashMap调用使用类型推断来避免必须像在普通构造函数调用中那样声明类型参数(除非您使用的是Java 7)。

答案 1 :(得分:3)

我不会去。

如果没有多线程的机会,你的第一个例子并没有做太多。 (属性线程安全吗?)

你的第二个例子很糟糕,因为当它很容易避免时,它会使用异常来定义程序流程。就个人而言,我会使用

public void change(Map<String,String> map) {
    if(map == null) throw new NullPointerException("map is null");
    Map<String,String> temp = new HashMap<String,String>(map);
    // continue with temp...
}

答案 2 :(得分:3)

绝对是第一种方式,但没有synchronized(除非你确定你需要它);如果您能够轻松可靠地预测是否会抛出异常,那么测试该条件比使用try / catch更具可读性(并且更有效)。但是,你不应该自己抛出NullPointerException - 而是抛出IllegalArgumentException

答案 3 :(得分:0)

在Java 7中,您可以使用Objects.requireNonNull检查引用是否不是null,如果引用则抛出NPE。

public static void change(Map<String, String> map){
    Objects.requireNonNull(map, "map should not be null");
    Map<String, Object> copy = new HashMap<>(map);
}

答案 4 :(得分:0)

我会做以下事情:

public void change(/*NonNull*/ Map<String, String> map) {
  if (map == null) {
      throw new IllegalArgumentException("Parameter must be nonnull"); 
  };
  //...
}

由于它是一个导出的方法,客户端应该在其抽象级别上获得异常,因此IllegalArgumentException优于NPE。

评论/*NonNull*/可以使用(pluggable type-)checker framework中的归零检查器在编译时检查。类似的东西也可能通过Findbugs,IDEA或Netbeans,但他们的检查不健全,即他们可能有误报。执行编程无效检查仍然有意义,因为客户端可能不会进行complie-time nullness检查(即使用checker框架/ Findbugs / IDEA / Netbeans /...).