“空指针”引用导致“程序异常退出”两例

本文分析了Android应用中常见的空指针异常原因,并通过两个具体案例详细展示了如何避免此类异常的发生,包括函数参数检查及确保构造函数的原子性。

最近,又偶尔发现在某些手机上会提示“程序异常退出”的情况,在android中,最通常的原因可能是资源引用的不正确(即findViewById函数引用的资源是错误的),或者是出现空指针问题。重新分析和review代码后,发现了几处可能引起问题的空指针引用。


1. 函数参数传入为空,在函数内部没有进行参数的检测。(例1)

2. 在实现一个类的构造函数时,发生异常,导致并没有构造出理解的对象,然后,再引用这个对象,其实是引用了一个null对象,导致程序发生“异常退出”。(例2)



1. 例1:函数参数传入为空,在函数内部没有进行参数的检测。

参考代码如下:

调用者:

public void run() {
    try {
        FileEngine.deleteFile(plainFilePath);
        ...

被调者FileEngine.deleteFile的实现:

public static boolean deleteFile(String filePath) {
    if (filePath == null) {
        return false;
    }
    File file = new File(filePath);
    if (!file.exists()) {
        return false;
    }
    if (file.isFile()) {
        return file.delete();
    } else {
        return false;
    }
}

错误异常:java.lang.NullPointerException

    atjava.io.File.<init>(File.java:277)


分析:可以在deleteFile函数内部进行参数的null值判断;

  或者,在调用deleteFile之前,进行输入参数的check。

 或者由于明知是文件操作,可以直接进行异常的捕获。


2. 例2:构造函数没有成功构造。

参考代码:

调用者:

LogWriter.getInstance().print("setOnItemLongClickListener===========000====");

被调用者LogWriter类中对应的函数实现:

public class LogWriter {
    private static LogWriter mLogWriter;
    private static String mPath;
    private static Writer mWriter;
    private static SimpleDateFormat df;

    private LogWriter() {
        mPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test";
        File file = new File(mPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        try {
            SimpleDateFormat df0 = new SimpleDateFormat("yy-MM-dd-HH-mm",Locale.getDefault());
            File logFile=new File(mPath,"Log-"+df0.format(new Date())+".txt");
            mWriter = new BufferedWriter(new FileWriter(logFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
        df = new SimpleDateFormat("[yy-MM-dd HH:mm:ss]: ", Locale.getDefault());
    }
    public static LogWriter getInstance() {
        if (mLogWriter == null) {
            mLogWriter = new LogWriter();
        }
        return mLogWriter;
    }
    public void close() throws IOException {
        mWriter.close();
    }
    public void print(String log) {
        try {
            mWriter.write(df.format(new Date()));
            mWriter.write(log);
            mWriter.write("\r\n");
            mWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

分析:

这里,实现了一个单例模式LogWriter,通常情况下这个它能够正常运转。但是,LogWriter有可能创建不成功(即构造函数可能抛出异常,),导致getInstance()得到的值是null,再调用它的print函数时,就造成空指针引用。

可见,保持构造函数的原子性,也是设计一个类时需要考虑的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值