1.0.0 Summary
Tittle:【Java】-NO.16.EBook.4.Java.1.010-【疯狂Java讲义第3版 李刚】- 异常
Style:EBook
Series:Java
Since:2017-09-29
End:....
Total Hours:...
Degree Of Diffculty:2
Degree Of Mastery:2
Practical Level:2
Desired Goal:2
Archieve Goal:....
Gerneral Evaluation:...
Writer:kingdelee
Related Links:
http://www.cnblogs.com/kingdelee/
1.异常
Check异常:编译阶段需要处理的异常(可以被修复的异常)。非RuntimeException及其子类的异常,都是Check异常。
Runtime异常:RuntimeException及其子类的异常,都是Runtime异常
1.2.catch之间是短路的,最多有且只有一个catch被执行,应从小到大依次写出。
1.3 捕获多个异常时的变量时,变量默认是final,捕获一个异常时,变量没有final
// 1 捕获多个异常时的变量时,变量默认是final,捕获一个异常时,变量没有final
public class MultiExceptionTest {
public static void main(String[] args) {
try {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
int c = a / b;
System.out.println("您输入的两个数相除的结果是:" + c);
} catch (IndexOutOfBoundsException | NumberFormatException
| ArithmeticException ie) {
System.out.println("程序发生了数组越界、数字格式异常、算术异常之一");
// 捕捉多异常时,异常变量默认有final修饰,
// 所以下面代码有错:
// ie = new ArithmeticException("test"); // ①
} catch (Exception e) {
System.out.println("未知异常");
// 捕捉一个类型的异常时,异常变量没有final修饰
// 所以下面代码完全正确。
e = new RuntimeException("test"); // ②
}
}
}
1.4 异常输出,可以是以一段流的方式输出异常跟踪信息,也可以是以一句字符串的信息输出异常描述信息
// 1.异常输出,可以是以一段流的方式输出异常跟踪信息,也可以是以一句字符串的信息输出异常描述信息
public class AccessExceptionMsg
{
public static void main(String[] args)
{
try
{
FileInputStream fis = new FileInputStream("a.txt");
}
catch (IOException ioe)
{
// 返回异常描述信息
// a.txt (系统找不到指定的文件。)
System.out.println(ioe.getMessage()); // 异常跟踪信息
// java.io.FileNotFoundException: a.txt (系统找不到指定的文件。)
// at java.io.FileInputStream.open0(Native Method)
// at java.io.FileInputStream.open(FileInputStream.java:195)
// at java.io.FileInputStream.<init>(FileInputStream.java:138)
// at java.io.FileInputStream.<init>(FileInputStream.java:93)
// at com.lee.test.java.ebook.crazy_java.u_10_exception.AccessExceptionMsg.main(AccessExceptionMsg.java:20)
ioe.printStackTrace();
}
}
}
1.5 try后面的catch(除非try里边的方法已经要throw了,所以要么跟着catch要么在方法中throw出去)、finally都是可选的。即,可以try接finally或者try接catch,但不能只单独写try。
// 1.try后面的catch(除非try里边的方法已经要throw了,所以要么跟着catch要么在方法中throw出去)、finally都是可选的。即,可以try接finally或者try接catch,但不能只单独写try。
public class AccessExceptionMsg2
{
public static void main(String[] args)
{
List list = null; try
{
list.add(1);
}finally {
System.out.println(list);
}
}
}
1.6 catch中的return仅表示该方法在此短路,最后仍继续执行finally的方法,并返回finally中的return(如果有的话)
1.7 catch只有使用System.exit(1);才不会执行finally
// 1.catch中的return仅表示该方法在此短路,最后仍继续执行finally的方法,并返回finally中的return(如果有的话)
// 2.下面的例子中,更好的表明return即表示结束,也表示结束并返回某值
public class FinallyTest
{
public static void main(String[] args)
{
int a = t1();
System.out.println("a:" + a); } public static int t1(){
FileInputStream fis = null;
boolean b = true;
try
{
fis = new FileInputStream("a.txt");
}
catch (IOException ioe)
{
System.out.println(ioe.getMessage());
// return语句强制方法返回
b = false;
return 1; // ①
// 使用exit来退出虚拟机
// System.exit(1); // ②
}
finally
{
// 关闭磁盘文件,回收资源
if (fis != null)
{
try
{
fis.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
System.out.println("执行finally块里的资源回收!");
return 2;
}
// 编译失败
// System.out.println("111111");
// return 3; }
}
1.8 异常要么处理,要么抛出给上一层调用者,若调用者依旧抛出,则直到main抛出被JVM捕获,输出异常,并中断程序
1.9 异常继承重写
1.重写方法的 两同两小一大 原则
1.1 两同:方法名相同 参数列表相同
1.2 两小:返回类型,异常 子类应比父类要小或者相同;
1.3 一大:修饰符 权限应该扩大或者相同
// 1.重写方法的 两同两小一大 原则
// 1.1 两同:方法名相同 参数列表相同
// 1.2 两小:返回类型,异常 子类应比父类要小或者相同;
// 1.3 一大:修饰符 权限应该扩大或者相同 class A{
A t1() throws Exception{
return new A();
}
} class B extends A{ public B t1() throws IOException{
return new B();
}
}
1.10 抛出runtime异常,调用者可以不catch,但是程序一旦到达main之后就中断了
// 1.抛出check异常,调用者需要catch;抛出runtime异常,调用者可以不catch,但是程序一旦到达main之后就中断了
public class ThrowTest
{
public static void main(String[] args)
{
try
{
// 调用声明抛出Checked异常的方法,要么显式捕获该异常
// 要么在main方法中再次声明抛出
throwChecked(-3);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
// 调用声明抛出Runtime异常的方法既可以显式捕获该异常,
// 也可不理会该异常
throwRuntime(3);
System.out.println("aa");
}
public static void throwChecked(int a)throws Exception
{
if (a > 0)
{
// 自行抛出Exception异常
// 该代码必须处于try块里,或处于带throws声明的方法中
throw new Exception("a的值大于0,不符合要求");
}
}
public static void throwRuntime(int a)
{
if (a > 0)
{
// 自行抛出RuntimeException异常,既可以显式捕获该异常
// 也可完全不理会该异常,把该异常交给该方法调用者处理
throw new RuntimeException("a的值大于0,不符合要求");
}
}
} //Exception in thread "main" java.lang.RuntimeException: a的值大于0,不符合要求
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.ThrowTest.throwRuntime(ThrowTest.java:47)
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.ThrowTest.main(ThrowTest.java:29)
1.11 自定义异常
public class MyException extends Exception { public MyException() {
} public MyException(String message) {
super(message);
}
}
1.12 catch and throw 企业对异常的使用 打印日志,在catch里将无法解决的异常抛出
// 1.企业打印异常的方式,将无法解决的异常抛出
public class AuctionTest {
private double initPrice = 30.0; // 因为该方法中显式抛出了AuctionException异常,
// 所以此处需要声明抛出AuctionException异常
public void bid(String bidPrice) throws AuctionException {
double d = 0.0;
try {
d = Double.parseDouble(bidPrice);
} catch (Exception e) {
// 此处完成本方法中可以对异常执行的修复处理,
// 此处仅仅是在控制台打印异常跟踪栈信息。
e.printStackTrace();
// // 1.企业打印异常的方式,将无法解决的异常抛出
// 再次抛出自定义异常
throw new AuctionException("竞拍价必须是数值," + "不能包含其他字符!");
}finally {
System.out.println("aaa");
}
if (initPrice > d) {
throw new AuctionException("竞拍价比起拍价低," + "不允许竞拍!");
}
initPrice = d;
System.out.println("bbb");
} public static void main(String[] args) {
AuctionTest at = new AuctionTest();
try {
at.bid("df");
} catch (AuctionException ae) {
// 再次捕捉到bid方法中的异常。并对该异常进行处理
System.err.println(ae.getMessage());
}
System.out.println("end");
}
}
//aaa
//end
//java.lang.NumberFormatException: For input string: "df"
//at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
//at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
//at java.lang.Double.parseDouble(Double.java:538)
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.AuctionTest.bid(AuctionTest.java:22)
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.AuctionTest.main(AuctionTest.java:42)
//竞拍价必须是数值,不能包含其他字符!
1.13 throw异常检查机制,虽然 throw的是Exception异常,但是在try中会检测实际的异常,FileInputStream的异常是FileNotFoundException,只需要抛出这个即可
// 1.throw异常检查机制,虽然 throw的是Exception异常,但是在try中会检测实际的异常,FileInputStream的异常是FileNotFoundException,只需要抛出这个即可
public class ThrowTest2
{
public static void main(String[] args) throws FileNotFoundException
// Java 6认为①号代码可能抛出Exception,
// 所以此处声明抛出Exception
// throws Exception
// Java 7会检查①号代码可能抛出异常的实际类型,
// 因此此处只需声明抛出FileNotFoundException即可。
{
try
{
// new FileOutputStream("a.txt");
InputStream inputStream = new FileInputStream("aaa.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
throw ex; // ①
}
}
}
1.14 一旦发生catch,都会中断try块内的代码不让其继续往下执行,但可以继续执行try之外的代码;在catch中出现throw,则直接中断catch所在的方法不让其继续往下执行
// 1. 一旦发生catch,都会中断try块内的代码不让其继续往下执行,但可以继续执行try之外的代码;在catch中出现throw,则直接中断catch所在的方法不让其继续往下执行
public class SalException extends Exception {
public SalException() {
} public SalException(String msg) {
super(msg);
} // 创建一个可以接受Throwable参数的构造器
public SalException(Throwable t) {
super(t);
} public static void main(String[] args) { try {
new A().t();
} catch (TooBigException e) {
System.out.println("1");
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out.println("2");
e.printStackTrace();
} catch (Exception e){
System.out.println("3");
e.printStackTrace();
}
System.out.println("main"); } } class A { public void tt(){ } // 一旦发生catch,都会中断try块内的代码不让其继续往下执行,但可以继续执行try之外的代码;在catch中出现throw,则直接中断catch所在的方法不让其继续往下执行
public void t() throws TooBigException, FileNotFoundException {
try {
t1(); // t2 t3 t4都没机会执行
t2();
t3();
t4();
} catch (FileNotFoundException e) {
e.printStackTrace();
// throw e;
} catch (TooBigException e) {
e.printStackTrace();
// throw e;
}
System.out.println("aaaa"); } public void t4(){
int [] a = {1, 2};
a[2] = 3;
} private void t3() throws FileNotFoundException {
try {
FileReader fileReader = new FileReader("aa.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
throw e;
}
} private void t2() {
String a = null;
try {
System.out.println(a.length());
} catch (NullException e) {
e.printStackTrace();
throw e;
}
} public void t1() throws TooBigException {
int a = 10;
int b = 11;
if (b > a) {
throw new TooBigException(" b > a");
}
}
} class FileException extends IOException{
public FileException() {
} public FileException(String message) {
super(message);
System.err.println("file error");
} public FileException(String message, Throwable cause) {
super(message, cause);
} public FileException(Throwable cause) {
super(cause);
}
} class NullException extends NullPointerException {
public NullException() {
} public NullException(String s) {
super(s);
System.err.println("null~~~~~~~~~~");
}
} class TooBigException extends Exception { public TooBigException() {
} public TooBigException(String message) {
super(message);
System.err.println("too big");
} public TooBigException(String message, Throwable cause) {
super(message, cause);
} public TooBigException(Throwable cause) {
super(cause);
} public TooBigException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
//too big
//aaaa
//main
//com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.TooBigException: b > a
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.A.t1(SalException.java:105)
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.A.t(SalException.java:60)
//at com.lee.test.java.ebook.crazy_java.u_10_exception.c_10_4_runtimeexception.SalException.main(SalException.java:35)
1.15 避免使用catch all,Throwable会捕获所有的异常,因为是*类,不易区分异常
catch (Throwable a){
a.printStackTrace();
}