import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.nio.channels.OverlappingFileLockException;
import java.security.spec.ECField;
import java.util.logging.Logger;
public class Ans {
public static void main(String[] args) {
//test2();
test4();
test5();
test6();
}
static void test0() {
//異常分爲兩類,error和exception,error是程序嚴重錯誤,無法恢復,包括:OutOfMemoryError 內存耗盡,NoClassDefFoundError 無法加載某個Class,StackOverflowError 棧溢出。Exception是運行時錯誤,可以捕捉並恢復,分爲RuntimeException(可以不被捕捉),和非RuntimeException(必須被捕捉)
//如果不想捕捉異常,可以在main函數中throws
}
static void test1() {
//由於異常捕獲從上向下,且捕獲一個後與其並列的不會再捕獲,所以子類異常應當寫在前面
//finally中的語句無論如何都會最後執行,且一定執行(沒有異常也執行)
}
static void test2() {
class A {
void a(String s) {
if (s==null)
throw new NullPointerException();
}
void b() {
try {
a(null);
} catch (Exception e) {
throw new IllegalArgumentException(); //如果這樣做就會丟失NullPointerException的信息
}
}
void b2() {
try {
a(null);
} catch (Exception e) {
throw new IllegalArgumentException(e); //這樣便可以保存以前的信息
}
}
void c() {
try {
a(null);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
finally {
throw new UnsupportedOperationException(); //這裏拋出一個異常會直接掩蓋前面的異常,因爲finally最後執行,且一段代碼只能拋出一個異常
} //但這種情況其實很少見
}
void c2() throws Exception {
Exception origin = null;
try {
a(null);
} catch (Exception e) {
origin = e;
throw new IllegalArgumentException(e);
}
finally {
Exception e = new UnsupportedOperationException();
if (origin!=null)
e.addSuppressed(origin); //這種方式可以解決異常掩蓋問題
throw e;
}
}
}
A a = new A();
try {
a.a(null);
} catch (Exception ne) {
ne.printStackTrace(); //這樣打印異常
}
try {
a.b();
} catch (Exception e) {
e.printStackTrace();
}
try {
a.b2();
} catch (Exception e) {
e.printStackTrace();
}
try {
a.c();
} catch (Exception e) {
e.printStackTrace();
}
try {
a.c2();
} catch (Exception e) {
e.printStackTrace();
}
}
static void test4() {
//在編寫程序時我們可以使用斷言
//這樣其實不會拋出錯誤,因爲JVM默認關閉斷言,需要在IDEA中設置,或者使用命令行
int i = -1;
assert i>0; //在這裏斷言失敗,會拋出AssertionError,由於時Error因此無法恢復,斷言常常用於開發和調試,而正式產品中應當使用異常
System.out.println(i);
assert i>0:"i must be larger than 0"; //斷言中可以包含信息
}
static void test5() {
//在編寫程序時的一個好習慣是生成日誌,日誌的好處在於減少用於就錯的代碼,而且有詳細的信息
//https://www.liaoxuefeng.com/wiki/1252599548343744/1264738568571776 可以查看博客信息,當然博客中講的也比較淺
//同時這種標準庫自帶的JDK Logging不是非常好用,以後可以試試更先進的
Logger logger = Logger.getGlobal();
logger.info("start process");
logger.severe("no no no");
}
static void test6() {
//Commons Logging是一個第三方日誌庫,需要載入工程中,它可以掛載不同的日誌系統,默認下使用Log4j,如果沒有就是用JDK Logging
class A {
void a() {throw new RuntimeException(); }
}
Log log = LogFactory.getLog(Ans.class);
log.info("begin");
log.warn("end");
try {
A a = new A();
a.a();
} catch (Exception e) {
log.error("catch it!!",e); //這種方法可以反映捕獲異常
}
}
static void test7() {
//Log4j的功能非常強大,由於其配置不方便,開發階段如果不需要引入Log4j可以暫時使用Commons Logging,此是Commons Logging默認使用JDK Logging
//等到需要使用Log4j時可以配置並使用,這時Commons Logging將自動切換至Log4j,不需要改動任何代碼
}
static void test8() {
//相對於Log4j 與Commons Logging,還擁有另一對日誌工具SLF4J與Logback
}
}