第十二章 通过异常处理错误
在以前平时的编程中没有真正意思到异常处理的强大,只从有一个android的图片过大,内存溢出,使用了异常处理才得以解决问题,我对异常处理的一个大概可以用一句话来表达:就是让程序在错误中恢复,依然进行下去
.概念
在c语言中,只有一些约定俗称的错误处理模式,而没有同意的异常处理机制,这使得编程人员思想趋向于只要你不随便乱点,就不会出错,否则就不关我事了,对我来说,这种想法是不要得的,并不是人人都是程序员,你的应用应该是强壮的,而我个人也就非常喜欢强壮的程序,java的异常处理机制是基于c++上面的,异常处理的一个很重要的好处就是将问题处理的代码和正常程序的代码分离开,使得代码的阅读,编写与调试工作更加井井有条
.基本异常
举一个例子,比如说除法,除数不能为0,或者不能为某些值,但是你不知道怎么去解决它,可以说是你意料之外,那么这时候你就应该抛出一个异常,然后异常处理程序处理(原来的执行路径将会打断),首先要在堆上new 一个异常对象,然后在当前环境中弹出对这个对象的引用,然后就把这个引用交给异常处理程序
异常参数,标准的异常类都有两个构造器,一个是默认的,一个是接受字符串作为参数的,以便将相关信息放入异常对象的构造器中
throw,抛出异常的引用,能够抛出任意类型的throwable对象,它是异常类型的根类,错误的信息保存在异常对象内部,然后上一层环境通过这些信息来决定如何处理异常
.捕获异常
监控区域,也就是try块,
处理程序,也就是catch块,可以使用多个catch,这样就可以针对性的来解决异常
.异常处理理论模型
终止模型。很容易理解,。就是发生了错误,然后异常处理可能进行了一些错误记录,然后系统就被迫终止
恢复模型。其实我们平时用的操作系统用的就是恢复模型,因为不可能,因为我们的误操作就要重启吧,可以在while里面加try,然后知道准确而至,这种虽然好,但是耦合度高,复杂性大,因为错误是千万种的,对于大型程序来说,维护与编写,无疑是噩梦
.自定义异常
必须从已有的异常类继承
throws,这个是为方法声明异常,当方法中有抛出异常时,必须声明,否则不能通过(runtimeexception及子类可以不用)注意:不建议在异常处理中放入过多的操作,耦合度会增加
printstatictrace()方法,打印从方法调用处直到异常抛出处
.异常与记录日志
这个非常重要,为什么呢。特别来说,我平时使用软件的时候,它都会将异常记录打印在一个文件上,然后你可以选择提交,这样帮助他们修复软件,在cam360里面就是这样
可以使用java.util.logging
.异常说明
throws ,因为源码不会与程序库一起发布
技巧:可以先声明异常,占个位置,然后不抛出异常,等以后有空再不上去
.捕获所有异常
exception放在最后
fillinstacktrace()可以使抛出点重置
.重新抛出异常
有两种,第一种是把原先的异常处理了,然后再抛出,第二种是把原先的异常处理,再新建一个异常抛出(原先的异常已解决),。。。使用throw e
.异常链
防止异常被屏蔽,可使用initcause
.java标准异常
throwable类可以被用来表示任何可以作为异常被抛出的类,且分为两种类型(继承),error,exception
runtimeexception称为不受检查异常,很难控制,只有代码的时候注意点
.finally清理
恢复状态的时候需要使用,无论是return,break,continue,都会使用finally
缺陷:在finally中使用throw,原先异常丢失,在finally中return根本不会报异常
.异常的限制
这样的异常实在繁琐
可能要等到以后自己成长了,才真正能体会到
注:
android 监听应用程序异常,输出异常日志log
- <pre class="java" name="code">1--在manifest添加:
- <application android:icon="@drawable/icon" android:label="@string/login_title"
- android:theme="@style/skin"
- android:name="com.XXX.application.LauncherApplication"
- android:process="@string/process" >
- public class LauncherApplication extends Application {
- private Context context;
- @Override
- public void onCreate () {
- super.onCreate();
- AppExcepiton appException = AppExcepiton.getInstance();
- appException.init(getApplicationContext());
- }
- public class AppExcepiton implements UncaughtExceptionHandler {
- // 获取application 对象;
- private Context mContext;
- private Thread.UncaughtExceptionHandler defaultExceptionHandler;
- // 单例声明CustomException;
- private static AppExcepiton appException;
- private AppExcepiton() {
- }
- public static AppExcepiton getInstance() {
- if (appException == null) {
- appException = new AppExcepiton();
- }
- return appException;
- }
- @Override
- public void uncaughtException(Thread thread, Throwable exception) {
- // TODO Auto-generated method stub
- String path = null;
- if (defaultExceptionHandler != null) {
- String state = Environment.getExternalStorageState();
- // 判断SdCard是否存在并且是可用的
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- path = Environment.getExternalStorageDirectory().getPath();
- }
- // 创建一个logcat目录
- path = path + "/eIVS/log";
- File file = new File(path);
- if (!file.exists()) {
- file.mkdir();
- }
- String time = getCurrentTime();
- String fileName = time.substring(0, 9);
- File myFile = new File(path+"/"+fileName+".log");
- String str = "\n"+time+"-->"+"["+exception.getLocalizedMessage()+"]";
- try {
- FileWriter fw = new FileWriter(myFile, true);
- fw.write(str);
- fw.flush();
- fw.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Log.e("tag", "exception >>>>>>>" + exception.getLocalizedMessage());
- // 将异常抛出,则应用会弹出异常对话框.这里先注释掉
- // defaultExceptionHandler.uncaughtException(thread, exception);
- }
- }
- /**
- * 获得当前时间
- * @return
- */
- public String getCurrentTime(){
- Time t = new Time();
- t.setToNow();
- int year = t.year;
- int month = t.month+1;
- int day = t.monthDay;
- int hour = t.hour;
- int minute = t.minute;
- int second = t.second;
- String time = year+"-"+month+"-"+day+" "+hour+":"+minute+":"+second;
- return time;
- }
- public void init(Context context) {
- mContext = context;
- defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
- Thread.setDefaultUncaughtExceptionHandler(this);
- }
3--在一个activity中模拟异常:
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.login);
- // 初始化资源信息
- throw new RuntimeException("--------");
- // init();
- }
- /**
- * 删除超过一年的日志
- * @param path
- */
- public void deleteOldFile(final String path){
- File file = new File(path);
- file.list(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String filename) {
- // TODO Auto-generated method stub
- File file = new File(path+"/"+filename);
- Long ago = file.lastModified();
- Long now = System.currentTimeMillis();
- //如果最后一次修改时间超过一年:3153600秒
- if((now-ago) > 31536000){
- file.delete();
- }
- return false;
- }
- });
- }
- //打印 有用信息 能够指出 错误代码的行数
- <pre class="java" name="code">@Override
- public void uncaughtException(Thread thread, Throwable exception) {
- // TODO Auto-generated method stub
- StackTraceElement[] stack = exception.getCause().getStackTrace();
- String path = null;
- if (defaultExceptionHandler != null) {
- String state = Environment.getExternalStorageState();
- // 判断SdCard是否存在并且是可用的
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- path = Environment.getExternalStorageDirectory().getPath();
- }
- // 创建一个logcat目录
- path = path + "/eIVS/log";
- File file = new File(path);
- if (!file.exists()) {
- file.mkdir();
- }
- //删除过期文件
- deleteOldFile(path);
- String time = getCurrentTime();
- String fileName = time.substring(0, 9);
- File myFile = new File(path+"/"+fileName+".log");
- try {
- String str = "\n"+time+"-->";
- FileOutputStream fos = new FileOutputStream(myFile,true);
- fos.write(str.getBytes());
- for (int i = 0; i < stack.length; i++) {
- fos.write(stack[i].toString().getBytes());
- }
- fos.flush();
- fos.close();
- } catch (Exception e) {
- } }
.异常的限制