android dev首页投稿(暂停使用,暂停投稿)

android 消灭NullPonintException的最佳

2016-05-23  本文已影响294人  康熙微博私访记

android 消灭NullPonintException的最佳方法

在java应用程序中,一个NullPonintException(空指针异常)是最好解决(问题)的方法。同时,空指针也是写健壮的顺畅运行的代码的关键。“预防好过治疗”这句话也同样适用于令人不爽的NullPonintException。通过应用防御性的编码技术和在遵守多个部分之间的约定,你可以再很大程度上避免NullPointException。下面的这些java小技巧可以最小化像!=null这种检查的代码。作为经验丰富的java程序猿,你可能意识到这些技术的某部分项目当中使用它。但是对于大学一年级学生和中级开发者,这是一个很好的学习机会。

这是一些很容易学会的简单技术,但是对于代码质量和健壮性来说确实很重要。以我的经验,仅是第一个小技巧就已经对改进代码质量具有很大的作用了。

1 String(字符串)调用 equal()和 equalsingnoreCase()而不是未知的对象

通常非空字符串调用equals(),因为equal()方法是对称的,调用a.equal()是同等于调用b.equal(),和这就是为什么很多部注意对象a和b,如果空的一边被调用会到导致空指针。

Object unknownObject = null;

//wrong way - may cause NullPointerException
if(unknownObject.equals("knownObject")){
   System.err.println("This may result in NullPointerException if unknownObject is null");
}

//right way - avoid NullPointerException even if unknownObject is null
if("knownObject".equals(unknownObject)){
    System.err.println("better coding avoided NullPointerException");
}

这是最重要的避免NullPointException的java技巧,但是结果会是极大的改进,因为equal()是一个很普遍的方法。

2 在两者返回相同结果的时候偏向使用valueOf()而非toString()

因为空对象调用toString()时会抛出NullPointException。如果我们可以通过调用value()得到相同的值的话,就应该使用valueOf()。这样会传递会一个空值。特别是在像Integer,Float,Double或者BigDecimla之类的包装类的情况下。

BigDecimal bd = getPrice();
System.out.println(String.valueOf(bd)); //doesn’t throw NPE
System.out.println(bd.toString()); //throws "Exception in thread "main" java.lang.NullPointerException"

如果你不确定你所使用的对象是否是空的时候,请使用这个JAVA技巧

3 使用TextUtils.isEmpty(str)来判断字符串的null和“”

Android提供了TextUtils类库,特别是isEmpty(str)兼容了null和“”空字符串两种情况的判断,方便而且安全。

String str = "";
String str = "str";
String str2 = null;

System.out.println(TextUtils.isEmpty(str));
System.out.println(TextUtils.isEmpty(str1));
System.out.println(TextUtils.isEmpty(str2));

output

true
false
true

但在作出任何结论之前,不要忘记阅读关于Null安全方法和类的文档。这是另一个java最佳操练,这不会要求你付出非常多的努力,但会让你获得很大的进步。

4 避免用返回空的collection或者空的array来代替从方法中返回Null

这个java技巧也是在Joshua Bloch的《Effective Java》所提及的。这本书也是一个提高JAVA编码能力的一个来源。通过返回一个空的collection或者一个空的array可以确定像size(),length()这种基础的调用不会抛出NullPointException。Collection类能够提供方便的空的List,Set和Map,(这些)有Collections.EMPTYLIST, Collections.EMPTYSET和 Collections.EMPTY_MAP这些能够被使用的(静态变量)。

代码如下;

public List getOrders(Customer customer){
   List result = Collections.EMPTY_LIST;
    return result;
}  

//支持泛型的list
public List<User> getUsers(int age){
   List<User> result = Collections.EMPTY_LIST;
    return result;
}

如果不用Collections.EMPTY_LIST,必须注意判断的顺序, 如下代码是推荐的写法:

if(null !=list && list.size() >0) {
    ....
}

类似地你可以使用Collections.EMPTYLIST, Collections.EMPTYSET和 Collections.EMPTY_MAP来代替返回Null。

5 使用@NonNull和@Nullable注解来约束方法参数和成员变量

当写你可以定义关于约定可空性(Nullability),要通过使用像@NonNull和@Nullable类似的注释提示这个方法是否为空安全(null safe)。现代的编译器,IDE和其他工具可以读出这个注释来帮你做一个空检查或者告诉你是否需要空检查。IntelliJIDE和findbugs 已经支持这种注释。这些注释也是JSR 305(译者注:可以理解为java的标准)的一部分。通过看到@NonNull和@Nullable,程序猿可以自己决定是否去进行空检查。顺便说下,对于JAVA程序猿来说,这是新的最好的实践,尽管需要一点时间去适应。

@Nullable
String ss;

@NonNull
IAdUtils adUtils;

在发布之前,通过lint检查,可以监控注解的变量。

6 遵循约定和定义合理的默认值

在java领域,一个最佳的避免空指针的方法之一就是和定下约定和遵守约定。大部分的NullPointException发生原因就是使用了一个不完整的信息或者并没有被提供所有的依赖信息来创建对象。如果你不允许创建不完整的对象和否定任何这种要求,你可以预防很多一段时间之后发生的NullPointException。如果对象被允许创建,那么你应该设定合理的默认值。例如,一个Employee(雇员)对象不可以在没有Id和Name属性的情况下被创建,但可以有一个可供选择的pghone number(电话号码)。如果Employee没有phone number,那么就用返回一个0来代替返回一个空值。但是这种处理必须非常小心地处理对空值的检查而不是检查非法输入。同样要注意,定义可以使空值的或者不可以空值的时候,提醒调用者作出被告知的决定。失败之后的选择或者接受空值也是一个你需要重视的重要设计。

7 使用try...catch...finally

如果你是在无法保证你代码的安全性,请用try...catch...finally来捕获异常,但是必须保证输出的可控性。

try {
    handleReceive(context, intent);
} catch (Throwable throwable) {
    throwable.printStackTrace();
} finally {
    //output
}

try {
    handleReceive(context, intent);
} catch (Exception ex) {
    ex.printStackTrace();
} finally {
    //output
}

try {
    handleReceive(context, intent);
} catch (Error error) {
    error.printStackTrace();
} finally {
    //output
}
上一篇下一篇

猜你喜欢

热点阅读