抛出异常分两步:
创建某个Exception
实例
用throw
语句抛出
知识点:当一个异常被抛出后,如果被别的方法捕获后又抛出了另一个异常,那就看不到原始异常了:当
process2()
抛出NullPointerException
后,被process1()
捕获,然后抛出IllegalArgumentException()
,那新的异常丢失了原始异常信息,就看不到原始异常NullPointerException
的信息了。
为了能追踪到完整的异常栈,在构造异常的时候,把原始的Exception
实例传进去,新的Exception
就可以持有原始Exception
信息,如下面代码的throw new IllegalArgumentException(e)
public class Main {
public static void main(String[] args) {
try {
process1();
} catch (Exception e) {
e.printStackTrace(); //可以打印异常的传播栈,对于调试非常有用
}finally {
System.out.println("End...");
}
}
static void process1(){
try {
process2();
}catch (NullPointerException e){
throw new IllegalArgumentException(e); //抛出两个异常
}
}
static void process2(){
throw new NullPointerException();
}
}
常见的做法是自定义一个BaseException
作为“根异常”,然后,派生出各种业务类型的异常。
BaseException
需要从一个适合的Exception
派生,通常建议从RuntimeException
派生,并且应提供多个构造方法:
public class BaseException extends RuntimeException {
public BaseException() {
super();
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(String message) {
super(message);
}
public BaseException(Throwable cause) {
super(cause);
}
}
其他业务类型的异常就可以从BaseException
派生:
public class UserNotFoundException extends BaseException {
}
public class LoginFailedException extends BaseException {
}
...
Java标准库定义的常用异常包括:
Exception
│
├─ RuntimeException
│ │
│ ├─ NullPointerException
│ │
│ ├─ IndexOutOfBoundsException
│ │
│ ├─ SecurityException
│ │
│ └─ IllegalArgumentException
│ │
│ └─ NumberFormatException
│
├─ IOException
│ │
│ ├─ UnsupportedCharsetException
│ │
│ ├─ FileNotFoundException
│ │
│ └─ SocketException
│
├─ ParseException
│
├─ GeneralSecurityException
│
├─ SQLException
│
└─ TimeoutException
配置不太方便,需要在JVM启动时传递参数
-Djava.util.logging.config.file=
Java标准库内置了日志包java.util.logging
。
JDK的Logging定义了7个日志级别,从严重到普通,INFO级别以下的日志不会被打印出:
Logger logger = Logger.getGlobal();
logger.info("start process...");
logger.warning("memory is running out...");
logger.fine("ignored."); //不会被打印出
logger.severe("process will be terminated...");
Commons Logging的特色是,它可以挂接不同的日志系统,并通过配置文件指定挂接的日志系统。默认情况下,Commons Loggin自动搜索并使用Log4j(Log4j是另一个流行的日志系统),如果没有找到Log4j,再使用JDK Logging。
Commons Logging定义了6个日志级别:
使用Commons Logging只需要和两个类打交道,并且只有两步:
LogFactory
获取Log
类的实例;Log
实例的方法打日志。import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Main {
public static void main(String[] args) {
Log log = LogFactory.getLog(Main.class);
try {
Integer.parseInt("abc");
} catch (Exception e) {
log.error("got exception!", e);
}
}
}
十月 10, 2019 11:18:43 下午 main.Main main
严重: got exception!
java.lang.NumberFormatException: For input string: “abc”
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at main.Main.main(Main.java:11)
导包步骤:
- 先去Apache官网[下载][https://commons.apache.org/proper/commons-logging/download_logging.cgi]
org.apache.commons.logging
包- 将
commons-logging-1.2.jar
放在工程的lib
目录下- 在IDEA中File –> Project Structure->Modules->Dependencies,点加号,选择jar包
注意:如果某个类是父类,那可以用getClass()
替代Person.class
。
因为这样子类的log
相当于LogFactory.getLog(Student.class)
,从父类继承而来,并且无需改动代码。
public class Person {
protected final Log log = LogFactory.getLog(getClass());
void foo() {
log.info("foo");
}
}
public class Student extends Person {
void bar() {
log.info("bar");
}
}