在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
在我的数据库中’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