所有的异常有Throwable(直接继承了Object)继承而来,有两个子类Error和Exception
Error , 描述了java运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这种类型的错误,当出现了这种错误,我们只能告诉使用者错误类型,安全的终止程序,没办法修复程序Exception层次的错误是我们需要关注的,Exception可以分为两个分支,一个是RuntimeException,由程序错误导致的异常是RuntimeException异常,是运行时异常(在运行时才可以发现的异常);另外一个是其他异常(IoException是其中的一个代表),编译时异常(编译时可以发现的异常) Runtime异常: 错误的类型转换 数组访问越界 访问空指针 其他异常: 试图在文件尾部读取数据 试图打开一个不存在的文件Error类和RuntimeException类的所以异常称为未检查异常,程序没有强制我们去处理这部分异常,其他的异常称为已检查异常,我们做了相应的处理。
异常的处理有两种,一种是使用try catch语句捕获异常进行处理,另一种是使用throws抛出异常,给方法的调用者处理。通常情况下,知道如何处理的异常直接捕获处理,不知道如何处理的异常要进行异常传递。
1.多个catch块的情况
多个catch块的情况, try 语句后面添加任意数量的 catch 块。如果保护代码中发生异常,异常被抛给第一个 catch 块。如果抛出异常的数据类型与第一个catch块匹配,它在这里就会被捕获。如果不匹配,它会被传递给第二个 catch 块。如此,直到异常被捕获或者通过所有的 catch块2.finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。无论是否发生异常,finally代码块中的代码总会被执行。3.try中有return时 try{} 里有一个 return 语句,那么紧跟在这个 try 后的 finally{} 里的 code 会不会被执行,什么时候被执行,在 return 前还是后?
会执行,在方法返回调用者前执行 在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,就会返回修改后的值。显然,在finally中返回或者修改返回值会对程序造成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java中也可以通过提升编译器的语法检查级别来产生警告或错误,Eclipse中可以在如图所示的地方进行设置,强烈建议将此项设置为编译错误。
在刚开始写程序的时候会用到好多System.out.println()来得到信息判断代码错误情况,在编码结束后会发现好多的打印无用信息,删除起来又比较麻烦。我们也可以自定义Logutils打印类,通过一个boolean类型的参数来控制调试期打印,发布程序不打印,下面简单写了一个
public class LogUtils { private LogUtils(){throw new AssertionError();} //是否打印flag private static boolean isPrint = true; //log打印语句 public static void log(String TAG , String msg){ if(isPrint){ System.out.println(TAG +": "+msg); } } //关闭log打印 public static void closeLog(){ if(isPrint == true){ isPrint = false; } } //开启log打印 public static void openLog(){ if(isPrint == false){ isPrint = true; } } }Java本身自带了Logger类来解决上述问题
#Logger简单使用,下面全部使用了全局打印logger public class Test { public static void main(String[] args) { // Logger.getGlobal().setLevel(Level.OFF); //在程序开始可以关闭所有打印语句,在发布期使用 // Logger.getGlobal().log(Level.FINE,"Open the menu"); //log第一个参数指定了打印级别 Logger.getGlobal().info("error"); //info()打印级别就是INFO级别 System.out.println("process exit "); } }Logger有下面7个日志级别,就和linux内核中的printk,android中的Log一样,一般每个级别代码打印信息的严重性不同,默认打印INFO及其以上的信息,可以在${jre}/lib/logging.properties中更改默认配置 - SERVER 最高的 - WARNING - INFO - CONFIG - FINE - FINER - FINEST 下面是网上一个博主分析的代码,存储到本地文件 http://blog.csdn.net/nash603/article/details/6749914
#输入文件到本地日志文件 public class LoggerUtil { /** 存放的文件夹 **/ private static String file_name = "邮政储蓄日志"; /** * 得到要记录的日志的路径及文件名称 * @return */ private static String getLogName() { StringBuffer logPath = new StringBuffer(); logPath.append(System.getProperty("user.home")); logPath.append("\\"+file_name); File file = new File(logPath.toString()); if (!file.exists()) file.mkdir(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); logPath.append("\\"+sdf.format(new Date())+".log"); return logPath.toString(); } /** * 配置Logger对象输出日志文件路径 * @param logger * @throws SecurityException * @throws IOException */ public static void setLogingProperties(Logger logger) throws SecurityException, IOException { setLogingProperties(logger,Level.ALL); } /** * 配置Logger对象输出日志文件路径 * @param logger * @param level 在日志文件中输出level级别以上的信息 * @throws SecurityException * @throws IOException */ public static void setLogingProperties(Logger logger,Level level) { FileHandler fh; try { String str = getLogName(); System.out.println(str); fh = new FileHandler(str,true); logger.addHandler(fh);//日志输出文件 //logger.setLevel(level); fh.setFormatter(new SimpleFormatter());//输出格式 //logger.addHandler(new ConsoleHandler());//输出到控制台 } catch (SecurityException e) { logger.log(Level.SEVERE, "安全性错误", e); } catch (IOException e) { logger.log(Level.SEVERE,"读取文件日志错误", e); } } public static void main(String [] args) { Logger logger = Logger.getLogger("sgg"); try { LoggerUtil.setLogingProperties(logger); logger.log(Level.INFO, "ddddd"); logger.log(Level.INFO, "eeeeee"); logger.log(Level.INFO, "ffffff"); logger.log(Level.INFO, "gggggg"); logger.log(Level.INFO, "hhhhhh"); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }