在Java中优雅地避免NullPointerException

考虑这一行:

if (object.getAttribute("someAttr").equals("true")) { // .... 

显然这行是一个潜在的错误,该属性可能为null ,我们将得到一个NullPointerException 。 所以我们需要将它重构为以下两种选择之一:

第一种选择:

 if ("true".equals(object.getAttribute("someAttr"))) { // .... 

第二种选择:

 String attr = object.getAttribute("someAttr"); if (attr != null) { if (attr.equals("true")) { // .... 

第一个选项难以阅读但更简洁,而第二个选项在意图上是明确的,但是很冗长。

在可读性方面,您更喜欢哪个选项?

我一直都在使用

 if ("true".equals(object.getAttribute("someAttr"))) { // .... 

因为虽然阅读起来有点困难,但它的冗长程度要低得多,我认为它足够可读,所以你很容易习惯它

在第二个选项中,您可以利用短路&&

 String attr = object.getAttribute("someAttr"); if (attr != null && attr.equals("true")) { // .... 

在某些情况下,简洁的方法从一开始就感觉不对,但有效地变得惯用。 这是其中之一; 另一个是这样的:

 String line; while ((line = bufferedReader.readLine()) != null) { // Use line } 

条件下的副作用? 不可想象的! 当你认识到特定的模式时,除了它基本上比替代品更好。

这种模式是类似的 – 它在Java中很常见,我希望任何有经验的开发人员能够识别它。 结果非常简洁。 (有时候,我有时会看到C#代码使用相同的习惯用语,不必要的 – 相等运算符在C#中使用字符串工作正常。)

底线:使用第一个版本,并熟悉它。

我喜欢选项1,我认为它足够可读。

选项3 btw将引入一个getAttribute方法,该方法将默认值作为参数。

总是渴望更短的代码,因为它们都是function相同的。 特别是在这样的情况下,不牺牲可读性。

Util.isEmpty(string) – 返回string == null || string.trim().isEmpty() string == null || string.trim().isEmpty()如果string == null ,则Util.notNull(string)返回“”,否则返回string。 Util.isNotEmpty(string)返回! Util.isEmpty(string)

我们有一个约定,对于字符串, Util.isEmpty(string)语义上表示true,而Util.isNotEmpty(string)语义上表示false。

这是一个非常好的问题。 我通常使用不优雅的:

 if (object.getAttribute("someAttr") != null && object.getAttribute("someAttr").equals("true")) { // .... 

(我不再使用它了)

我有另一个答案;

 List> group = jjDatabase.separateRow(db.Select("SELECT * FROM access_user_group WHERE user_id=1 ;")); 

在我的数据库中’access_user_group’中没有“group_c80”作为列,因此在get(0).get(“group_c80”)中,空指针exception符合。 但我通过以下代码处理它:

 for (int j = 1; j < 100; j++) { String rulId="0";//defult value,to privent null pointer exeption in group_c try { rulId = group.get(0).get("group_c" + j)).toString(); } catch (Exception ex) { ServerLog.Print( "Handeled error in database for " + "group_c" + (j < 10 ? "0" + j : j) +"This error handeled and mot efect in program"); rulId = "0"; }} 

这是我的方法,虽然需要一个PropertyUtil类,但它只写了一次:

 /** * Generic method to encapsulate type casting and preventing nullPointers. * * @param  The Type expected from the result value. * @param o The object to cast. * @param typedDefault The default value, should be of Type T. * * @return Type casted o, of default. */ public static  T getOrDefault (Object o, T typedDefault) { if (null == o) { return typedDefault; } return (T) o; } 

客户端代码可以这样做:

 PropertyUtil.getOrDefault(obj.getAttribute("someAttr"), "").equals("true"); 

或者,对于列表:

 PropertyUtil.getOrDefault( genericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST ).contains(element); 

或者对List的消费者,拒绝对象:

 consumeOnlyList( PropertyUtil.getOrDefault( enericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST ) ) 

默认值可能是空对象模式的impl https://en.wikipedia.org/wiki/Null_Object_pattern