提问人:Yuval Adam 提问时间:6/8/2009 最后编辑:Jon SeigelYuval Adam 更新时间:10/25/2016 访问量:7371
在 Java 中优雅地避免 NullPointerException
Gracefully avoiding NullPointerException in Java
问:
请考虑以下行:
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"))) { // ....
因为虽然它有点难读,但它不那么冗长,而且我认为它的可读性足够强,所以你很容易习惯它
我喜欢选项 1,我认为它足够可读。
顺便说一句,选项 3 是引入一个将默认值作为参数的 getAttribute 方法。
评论
Util.isEmpty(string)
- returns return “” if , string 否则。 返回!string == null || string.trim().isEmpty()
Util.notNull(string)
string == null
Util.isNotEmpty(string)
Util.isEmpty(string)
我们有一个约定,对于字符串,语义上意味着真,语义上意味着假。Util.isEmpty(string)
Util.isNotEmpty(string)
在第二个选项中,您可以利用短路:&&
String attr = object.getAttribute("someAttr");
if (attr != null && attr.equals("true")) { // ....
评论
始终渴望更短的代码,因为两者在功能上是等效的。尤其是在这样不牺牲可读性的情况下。
在某些情况下,简洁的方法一开始感觉是错误的,但实际上变成了惯用语。这是其中之一;另一个是这样的:
String line;
while ((line = bufferedReader.readLine()) != null) {
// Use line
}
某种情况下的副作用?不可想象!除了当您识别特定模式时,它基本上比替代品更好。
这种模式是相似的——它在 Java 中非常普遍,我希望任何有相当经验的开发人员都能识别它。结果令人愉快地简洁。(有趣的是,我有时会看到 C# 代码不必要地使用相同的习语 - 相等运算符适用于 C# 中的字符串。
底线:使用第一个版本,并熟悉它。
这是一个很好的问题。 我通常使用不优雅的:
if (object.getAttribute("someAttr") != null && object.getAttribute("someAttr").equals("true")) { // ....
(我不会再使用它了)
评论
我还有另一个答案;
List<Map<String, Object>> group = jjDatabase.separateRow(db.Select("SELECT * FROM access_user_group WHERE user_id=1 ;"));
在我的数据库中,“access_user_group”中没有“group_c80”列,因此在 get(0).get(“group_c80”) 中,空指针异常一致。但我通过以下代码处理了它:
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 <T> 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> 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 的使用者,这将拒绝 Object:
consumeOnlyList(
PropertyUtil.getOrDefault(
enericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST
)
)
默认值可能是 null 对象模式的 impl https://en.wikipedia.org/wiki/Null_Object_pattern
评论