Java 提高(4)----- 异常 Logger

异常 Logger


推荐博客 http://blog.csdn.net/hguisu/article/details/6155636

异常分类

此处输入图片的描述
所有的异常有Throwable(直接继承了Object)继承而来,有两个子类Error和Exception

  1. Error , 描述了java运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这种类型的错误,当出现了这种错误,我们只能告诉使用者错误类型,安全的终止程序,没办法修复程序
  2. Exception层次的错误是我们需要关注的,Exception可以分为两个分支,一个是RuntimeException,由程序错误导致的异常是RuntimeException异常,是运行时异常(在运行时才可以发现的异常);另外一个是其他异常(IoException是其中的一个代表),编译时异常(编译时可以发现的异常)
Runtime异常:
    错误的类型转换
    数组访问越界
    访问空指针
其他异常:
    试图在文件尾部读取数据
    试图打开一个不存在的文件

Error类和RuntimeException类的所以异常称为未检查异常,程序没有强制我们去处理这部分异常,其他的异常称为已检查异常,我们做了相应的处理。

自定义异常

#自定义异常只要类继承了Exception或者子类就可以
#包含两个构造器,一个是默认的构造器,另一个是有打印信息的构造器
public class PrivateException extends Exception {
    public PrivateException() {
    }
    public PrivateException(String message) {
        super(message);
    }
}
#使用
    public static void main(String[] args) {
        for(int i = 0; i < 10;i++){
            if(i == 5){
                try {
                   //代码1 throw new PrivateException();
                   //代码2 throw new PrivateException("I am here error");
                } catch (PrivateException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    #代码1结果
    #demo.Crazy.four.PrivateException
    #at demo.Crazy.four.Test.main(Test.java:11)
    #代码2结果,代码2打印出了我们声明的错误信息 I am here error
    #demo.Crazy.four.PrivateException: I am here error
    #at demo.Crazy.four.Test.main(Test.java:11)

异常的处理

异常的处理有两种,一种是使用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中可以在如图所示的地方进行设置,强烈建议将此项设置为编译错误。

异常处理技巧

  • 避免过大的try块,这样出错时不容易定位到错误
  • 细化异常的类型,不要不管什么异常都写成Exception,这样虽然代码可简单
  • catch块尽量捕获一类异常,当你选择了捕获异常就应该对它负责,不要只是打印异常,否则就直接抛出异常
  • 不要把自己能处理的异常抛出去
  • 不要使用try…catch参与流程控制
  • 在多个catch时在最后加上catch(Exception),避免遗漏异常

Logger机制

在刚开始写程序的时候会用到好多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();
        }

    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值