最近,又偶尔发现在某些手机上会提示“程序异常退出”的情况,在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之前,进行输入参数的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函数时,就造成空指针引用。
可见,保持构造函数的原子性,也是设计一个类时需要考虑的。