在类中实例化私有变量以避免使用变量时出现NullPointerException是不好的做法,例如:
public Class MyClass{
private HashMap<String, String> myHashMap = new HashMap<String, String>();
public HashMap<String, String> getMyHashMap (){return myHashMap; }
public HashMap<String, String> setMyHashMap (String myString){ /* treatment to set the myHashMap under some conditions */}
}
如果我们没有实例化myHashMap,方法getMyHashMap()可能会返回 null getMyHashMap()的调用者检查null值是一种更好的做法吗? 在这种情况下是否有适用的编码良好做法?
答案 0 :(得分:2)
我在这种情况下使用两种解决方案。如果myHashMap
必须始终可用,请将其设置为final
并使用值初始化:
private final HashMap<String, String> myHashMap = new HashMap<String, String>();
public HashMap<String, String> getMyHashMap () {
return myHashMap;
}
如果myHashMap
比空对象大,我宁愿做一些像延迟加载的事情:
private HashMap<String, String> myHashMap;
public HashMap<String, String> getMyHashMap () {
if (myHashMap == null) {
myHashMap = new HashMap<String, String>();
}
return myHashMap;
}
答案 1 :(得分:1)
完全可以。
编程中的常见模式是迭代从方法返回的集合或映射。如果方法可能返回null
,则在尝试迭代集合或映射之前,调用者有责任执行空检查。因此,从返回集合或映射的公共方法返回null
通常被认为是不好的做法。一个更好的选择是返回一个空集合或映射,因为它们允许安全迭代而不会出现NullPointerException。
虽然不推荐,但可以从返回集合或映射的私有方法返回null
,因为它们的范围仅限于封闭类。
答案 2 :(得分:1)
没有。这不是一个坏习惯。
通过这样做,您正在为该类建立一个不变量: myHashMap
不为空。这个不变量使得对其他类的正确运行的推理变得更容易:您知道myHashMap
不为空,因此当您尝试访问它时,您将无法获得NullPointerException
。
您可以通过在初始化程序块(您的代码等效)中指定值或在构造函数中指定值来实现此目的。这两个大致等价;实际上,当您声明它时,为该字段分配变为初始化块,该块在构造函数之前执行。
您可以通过myHashMap
最终来强化您对此不变量的依赖:这意味着您以后无法将其意外设置为null
。
你并不严格需要这个不变量:正如@hsz建议的那样,你可以懒惰地使值非空。但是,我认为这会使课堂变得混乱,并且更难以推理。更改类以添加新功能也更加困难:如果需要访问myHashMap
,则必须记住将该实例化添加到新代码中。
我想说,在创建实例时,一劳永逸地创建它,然后继续使用其余的代码 - 尤其是对于像空HashMap
这样简单的事情。
答案 3 :(得分:0)
您可以在构造函数中实例化地图。
public Class MyClass{
private HashMap<String, String> myHashMap;
public MyClass(){
myHashMap = new HashMap<String, String>();
}
public HashMap<String, String> getMyHashMap (){ return myHashMap; }
public HashMap<String, String> setMyHashMap (String myString){ /* treatment to set the myHashMap under some conditions */}
}
这样,getMyHashMap
永远不会返回null