java筆記5-java異常處理
Java的異常
異常
Java使用異常Exception來表示錯誤
- Exception是Class,帶有型別資訊
- 可以在任何地方丟擲
- 只需要在上層捕獲,和方法呼叫分離
必須捕獲的異常稱為Checked Exception
不需要捕獲的異常包括RuntimeException和Error
捕獲異常使用try...catch
不捕獲的Checked Exception必須用throws宣告
main()是最後捕獲異常的機會
捕獲異常
捕獲異常使用try...catch
catch會捕獲對應的Exception及其子類
多個catch子句從上到下匹配
順序非常重要,子類必須在前
finally保證有無錯誤都會執行
finally可選
使用multi-catch捕獲多種型別異常
丟擲異常
異常從下往上丟擲,直至被捕獲
列印方法呼叫棧:printStackTrace()
用throw語句丟擲異常
轉換異常時注意保留原始異常資訊
丟擲異常前會保證執行finally
finally如果丟擲異常會導致suppressed exception
獲取所有異常資訊:getSuppressed()
自定義異常
儘量使用JDK已定義異常
自定義異常從RuntimeException派生
先定義BaseException,再派生子類
自定義異常應該提供多個構造方法
可以使用IDE根據父類快速建立構造方法
斷言 Assertion
斷言使用assert語句
JVM預設關閉斷言指令:
- 給Java虛擬機器傳遞-ea引數啟用斷言
- 可以指定特定的類啟用斷言 -ea:com.feiyangedu.sample.Main
- 可以指定特定的包啟用斷言 -ea:com.feiyangedu...
特點:
- 斷言是一種除錯方式,斷言失敗會丟擲AssertionError,導致程式退出
- 只能在開發和測試階段啟用斷言
- 對可恢復的錯誤不能使用斷言,而應該丟擲異常
- 斷言很少被使用,更好的方法是編寫單元測試
使用JDK Logging
日誌 Logging
- 日誌是為了替代System.out.println(),可以定義格式,重定向到檔案等
- 日誌可以存檔,便於追蹤問題
- 日誌記錄可以按級別分類,便於開啟或關閉某些級別
- 可以根據配置檔案調整日誌,無需修改程式碼
JDK提供了Logging:java.util.logging
JDK Logging定義了7個日誌級別:
- SEVERE
- WARNING
- INFO (預設級別)
- CONFIG
- FINE
- FINER
- FINEST
JDK Logging的侷限:
- JVM啟動時讀取配置檔案並完成初始化
- JVM啟動後無法修改配置
- 需要在JVM啟動時傳遞引數 -Djava.util.logging.config.file=config-file-name
package com.feiyangedu.sample;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
public static void main(String[] args) {
Logger logger = Logger.getGlobal();
logger.setLevel(Level.WARNING);
logger.info("Create new person...");
Person p = new Person("Xiao Ming");
System.out.println(p.hello());
try {
new Person(null);
} catch (Exception e) {
logger.log(Level.WARNING, "Create new person failed", e);
}
logger.info("Program end.");
}
}
package com.feiyangedu.sample;
public class Person {
private final String name;
public Person(String name) {
if (name == null) {
throw new IllegalArgumentException("name is null.");
}
this.name = name;
}
public String hello() {
return "Hello, " + name + "!";
}
}
輸出:
Hello, Xiao Ming!
十二月 16, 2018 3:43:17 下午 com.feiyangedu.sample.Main main
警告: Create new person failed
java.lang.IllegalArgumentException: name is null.
at com.feiyangedu.sample.Person.<init>(Person.java:9)
at com.feiyangedu.sample.Main.main(Main.java:15)
使用Commons Logging
Commons Logging
Commons Logging是Apache建立的日誌系統:
- Commons Logging是使用最廣泛的日誌模組
- Commons Logging的API非常簡單
- Commons Logging可以自動使用其他日誌模組
Commons Logging定義了6個日誌級別:
- FATAL
- ERROR
- WARNING
- INFO (預設級別)
- DEBUG
- TRACE
在Eclipse中引入jar包:
Project -> Property -> Java Build Path -> Libraries -> Add Jars...
初始化Log物件:
final Log log = LogFactory.getLog(getClass());
文件:http://commons.apache.org/proper/commons-logging/
package com.feiyangedu.sample;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Main {
static Log log = LogFactory.getLog(Main.class);
public static void main(String[] args) {
Person p = new Person("Xiao Ming");
log.info(p.hello());
try {
new Person(null);
} catch (Exception e) {
log.error("Exception", e);
}
}
}
package com.feiyangedu.sample;
public class Person {
private final String name;
public Person(String name) {
if (name == null) {
throw new IllegalArgumentException("name is null.");
}
this.name = name;
}
public String hello() {
return "Hello, " + name + "!";
}
}
輸出:
十二月 16, 2018 3:39:46 下午 com.feiyangedu.sample.Main main
資訊: Hello, Xiao Ming!
十二月 16, 2018 3:39:46 下午 com.feiyangedu.sample.Main main
嚴重: Exception
java.lang.IllegalArgumentException: name is null.
at com.feiyangedu.sample.Person.<init>(Person.java:9)
at com.feiyangedu.sample.Main.main(Main.java:13)
使用Log4j
Log4j
Log4j的概念:
- Appender
- Filter
- Layout
使用Log4j:
- 通過Commons Logging實現日誌,不需要修改程式碼即可使用Log4j
- 使用Log4j只需要把log4j2.xml和相關jar放入classpath
- 如果要更換Log4j,只需要移除log4j2.xml和相關jar
- 只有擴充套件Log4j時,才需要引用Log4j的介面
文件:http://logging.apache.org/log4j/
package com.feiyangedu.main;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.feiyangedu.sample.Person;
public class Main {
static final Log log = LogFactory.getLog(Main.class);
public static void main(String[] args) {
log.debug("Program start...");
String name = "Xiao Ming";
log.info("Create person " + name);
Person p = new Person(name);
log.info("call hello(): " + p.hello());
try {
new Person(null);
} catch (Exception e) {
log.error("Error when create person.", e);
}
log.info("Program end.");
}
}
package com.feiyangedu.sample;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Person {
final Log log = LogFactory.getLog(getClass());
private final String name;
public Person(String name) {
if (name == null) {
throw new IllegalArgumentException("name is null.");
}
this.name = name;
}
public String hello() {
log.debug("Say hello to: " + name);
return "Hello, " + name + "!";
}
}
log4j2.xml放在src下
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<!-- 如何列印日誌的格式 -->
<Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36}%n%msg%n%n</Property>
<Property name="file.all.filename">log/all.log</Property>
<Property name="file.all.pattern">log/all.%i.log.gz</Property>
<Property name="file.err.filename">log/err.log</Property>
<Property name="file.err.pattern">log/err.%i.log.gz</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${log.pattern}" />
</Console>
<RollingFile name="all" bufferedIO="true" fileName="${file.all.filename}"
filePattern="${file.all.pattern}">
<PatternLayout pattern="${log.pattern}" />
<Policies>
<!-- 每當log檔案達到1M時就自動切割 -->
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingFile>
<RollingFile name="err" bufferedIO="true"
fileName="${file.err.filename}" filePattern="${file.err.pattern}">
<PatternLayout pattern="${log.pattern}" />
<Policies>
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="console" level="info" />
<AppenderRef ref="all" level="info" />
<AppenderRef ref="err" level="error" />
</Root>
<Logger name="com.feiyangedu.sample" level="debug">
<AppenderRef ref="console" level="debug" />
</Logger>
</Loggers>
</Configuration>