一、异常处理
1.异常介绍
Throwable是异常体系的根,它继承自Object。Throwable有两个体系:Error和Exception
Error(错误)是系统中的错误,程序员是不能改变的和处理的,是在程序编译时出现的错误,只能通过修改程序才能修正。一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止
Exception(异常)表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常(程序逻辑编写不对造成的,应该修复程序本身)
2.捕获异常
捕获异常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类:
我们通常捕获所有异常的父类Exception 在能确定异常的情况下使用多 catch 块来捕获异常来明确异常信息
finally块用来保证一些代码必须执行
3.抛出异常
1.创建某个Exception的实例;
2.用throw语句抛出;
4.自定义异常
通常会创建一个类并集成BaseException,然后派生出各种业务类型的异常。 BaseException继承自RuntimeException,继承多个构造方法,这样抛出异常的时候,就可以选择合适的构造方法
BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生
5.断言
主要使用在代码开发和测试时期,用于对某些关键数据的判断,如果这个关键数据不是你程序所预期的数据,程序就抛出AssertionError异常提出警告或退出(默认关闭)
6.日志
在JDK 1.3及以前,Java打日志依赖System.out.println(), System.err.println()或者Exception的printStackTrace()方法来实现,现在常用的日志框架有JDK Logging、Log4j、SLF4J、Logback
通常一个类只有一个 LOG 对象,如果有父类可以将 LOG 定义在父类中
使用JDK Log进行日志打印操作如下
使用Java标准库内置的Logging一旦开始运行,就无法修改配置所以Java标准库内置的Logging使用并不是非常广泛
log4j
Log4j的配置一般放在文件里(log4j.properties、log4j.xml) 由三个重要的组成构成:日志记录器(Loggers),输出端(Appenders)和日志格式化器(Layout)
1.Logger:控制要启用或禁用哪些日志记录语句,并对日志信息进行级别限制
2.Appenders : 指定了日志将打印到控制台还是文件中 3.Layout : 控制日志信息的显示格式
Log4j中将要输出的Log信息定义了5种级别,依次为DEBUG、INFO、WARN、ERROR和FATAL
日志级别 | 描述 |
OFF 关闭 | 最高级别 不输出日志 |
TRACE 跟踪 | 输出更细致的程序运行轨迹 |
DEBUG 调试 | 输出更细致的对调试应用有用的信息 |
INFO 信息 | 输出应用运行过程的详细信息 |
WARN 警告 | 输出可能潜在的危险状况 |
ERROR 错误 | 输出错误,但应用还能继续运行 |
FATAL 致命 | 输出非常严重的可能会导致应用程序终止的错误 |
ALL 所有 | 输出所有级别信息 |
Slf4j、Logback
Slf4j 也是现在主流的日志门面框架,使用 Slf4j 可以很灵活的使用占位符进行参数占位,简化代码,拥有更好的可读性. Logback 是 Slf4j 的原生实现框架,同样也是出自 Log4j 一个人之手,但拥有比 log4j 更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流
SLF4J的日志采用接口传入的形式 而且增加了可以带占位符的字符串写法,用后面的变量自动替换占位符
二、反射
1.概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2.Class
创建的每一个类也都是对象,即类本身是java.lang.Class类的实例对象,这个实例对象称之为类对象,也就是Class对象,jvm中有很多的实例,每个类都有唯一的Class对象.
一个类被加载到内存并供我们使用需要经历三个阶段 加载、链接、初始化.
所有的类都是在对其第一次使用时,动态加载到JVM中的(懒加载),因此java程序程序在它开始运行之前并非被完全加载,其各个类都是在必需时才加载的,在类加载阶段,类加载器首先检查这个类的Class对象是否已经被加载如果尚未加载,默认的类加载器就会根据类的全限定名查找.class文件
获取class的方式有三种
1.Class.forName(“类的全限定名”) 2.实例对象.getClass() 3.类名.class (类字面常量)
获取数据
setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对java和javax开头的package的类调用setAccessible(true),这样可以保证JVM核心库的安全
方法
动态代理
JDK动态代理就是要生成一个包装类对象,由于代理的对象是动态的,所以叫动态代理。由于我们需要增强,这个增强是需要留给开发人员开发代码的,因此代理类不能直接包含被代理对象,而是一个InvocationHandler,该InvocationHandler包含被代理对象,并负责分发请求给被代理对象,分发前后均可以做增强