异常机制是java一个重要的点,源码中经常可以看到它的身影,现在重新破解它
异常的定义:导致程序发生错误的行为
一,异常机制的分类和体系结构关系
一,异常机制的分类
异常机制把异常分为两种:错误(Error)和异常(Exception),而异常又分为两种编译期异常(IOExecption)和运行时异常(RuntimeExecption)
Error:错误在机制中不做任何处理,jvm本身也无法解决,只能后期修改避免,我们不重点说明
Error也分两类:
1,IOError(IO错误):出现严重IO错误时抛出
2,VirtualMachineError(虚拟机错误):虚拟机已损坏或已耗尽资源以使其继续运行 例如:OutOfMemoryError(堆溢出OOM),StackOverflowError(栈溢出)
异常:
1,编译期异常:在编写代码时会有提示抛出或者声明 常见的有:IOExecption(IO异常),FileNotFountExecption(文件异常)
2,运行期异常(RuntimeException):编译期间没有任何提示信息,运行时报错,常见的有:NullPointerException(空指针异常),ArrayIndexOutOfBoundsException(数组越界), ClassCastException(类型转换异常),ArithmeticException(算数异常)
二,异常机制的体系结构图
总体架构层次图:
一,顶级父类:Throwable
Throwable:只有两个子类error和exception
二,error类
error下的jvm错误类:
三,异常类
在异常类中并没有严格的划分运行时异常和编译期异常,除非运行时运行的是编译器异常
运行时异常类:
三,常见的错误或异常例子
一,Error
1,OutOfMemoryError(堆溢出)
int[] n=new int[1024*1024*1024]; //堆溢出
结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at 异常.WQL.main(WQL.java:9)
2,StackOverflowError(栈溢出)
public static void g() { g(); }
结果:
Exception in thread "main" java.lang.StackOverflowError at 异常.WQL.g(WQL.java:28) at 异常.WQL.g(WQL.java:28) at 异常.WQL.g(WQL.java:28)
二,运行时异常
1,NullPointerException(空指针)
String[] a=null; System.out.print(a[1]);
结果:
Exception in thread "main" java.lang.NullPointerException at 异常.WQL.main(WQL.java:14)
2,ArrayIndexOutOfBoundsException(数组越界)
int[] a=new int[3]; System.out.print(a[4]);
结果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 3 at 异常.WQL.main(WQL.java:17)
3,ClassCastException(类型转换异常)
Object a=new test1(); String b=(String)a;
结果:
Exception in thread "main" java.lang.ClassCastException: class 枚举.test1 cannot be cast to class java.lang.String at 异常.WQL.main(WQL.java:20)
4,ArithmeticException(算数异常)
System.out.print(0/0);
结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero at 异常.WQL.main(WQL.java:22)
二,异常的处理
异常的的处理分为两种方式:
1,try..catch 捕获异常
2,throws 声明异常
一,异常处理模式
java异常机制采用的是抓抛模型
抓抛模式:
1,抛异常:
自动抛异常:出程序在正常运行时,出现异常,JVM会生产一个异常对象并抛出,程序中断
手动抛异常:在程序定义时,在可能发生错误的代码,手动抛出异常 (格式:new 异常类型("说明"))
2,抓异常:将程序抛出的异常进行处理,
声明式处理异常:通过throws将程序抛出的异常,再次抛出给程序的调用者,如果调用者再抛出最终抛给jvm处理,它本身不做处理
捕获式处理异常:通过try{}catch(){}finally{}将程序抛出的异常进行捕获处理
声明式异常和捕获式异常的区别:
1,定义方式:throws定义再方法头部,try{}catch定义在程序代码段中
2,处理方式:throws本身并不处理异常,只是抛出由调用者处理,像是自己不做事,将事情推由别人来做,try.catch本身处理异常
3,程序中断:throws定义在方法头部,程序程序异常,方法直接中断,异常后面的代码不会被执行,try.catch中的程序出现异常,异常处理完毕代码会继续执行
4,适应范围:throws定义方法所有编译期异常,都会被抛出,try.catch只能处理try内的异常
二,Throwable异常中的方法
构造方法:
方法:
三,throws处理异常
1,throws修饰在方法的声明处,在方法运行时出现异常时,生成一个异常对象,如果异常对象跟throws声明类型匹配,throws就会将方法抛出
throws把异常抛出给方法的调用者,调用throws的修饰的方法,要么继续throws抛出,要么捕获
public static void main(String[] args) {
g();
}
public static void g() throws NullPointerException {
System.out.print("wql");
}
2,方法重写throws的规则
重写方法,只能throws和父类相同的或者父类子类的异常类型
abstract class k { public abstract void h() throws RuntimeException; } class j extends k{ @Override public void h() throws NumberFormatException { // NumberFormatException是RuntimeException的子类 // TODO Auto-generated method stub }
四,try{}catch(){}finally{}捕获异常
try{}catch是程序自身处理异常,catch匹配出现异常,不匹配将捕获异常失败
try:可能出现异常的代码段
catch:假如try中出现异常,就匹配catch中的异常,并执行catch中的语句
finall:无论是否捕获都执行的代码段
例:
try{ System.out.print(0/0); }catch(ArithmeticException a){ a.printStackTrace(); System.out.print("哈哈哈"); }
结果:
java.lang.ArithmeticException: / by zero at 异常.FQ.main(FQ.java:8) 哈哈哈
try...catch和throws的具体用途:
1,运行时异常其实是在代码编写中很难发现的,不知道那一段代码会出问题,运行时才会发现,这种异常可以不做处理,JVM会自动抛出,也可以直接在方法中声明throws
2,编译期异常在程序编译时就通不过,有具体的代码段,用try...catch直接处理比较合适,不用throws,但也有特例
3,在编译期异常,程序有大量的变量赋值定义和方法引用,try...catch就不是最好的选择了,但try出现异常,变量赋值出现错误,catch的数据也会出错,直接throws中断程序是 最好的
五,自定义异常
一,手动抛异常
手动抛出异常在一些源代码中被大量用到,但数值或者方法引用违反当前自定义程序时(但并没有违法JVM构造和编译规则,不会自动产生异常对象),只有手动抛出异常才能终止程序,它和自定义异常常相伴相生,
注:手动抛出的异常也可以处理
格式:throw new 异常类("提示符")
它和throwable的构造方法一致
例:
public class FQ { public static void main(String[] args) { WQL(10); } public static void WQL(int a) { if(a > 100) { System.out.print(a); }else { throw new ArithmeticException("数字违法!!"); //手动抛出异常 } }
结果:
Exception in thread "main" java.lang.ArithmeticException: 数字违法!! at 异常.FQ.WQL(FQ.java:16) at 异常.FQ.main(FQ.java:6)
二,自定义异常
自定义异常也不能说是真正的自定义,它需要基础现有的异常结构
步骤:
1,继承一个现有的异常类
2,提供一个全局的序列号:static final long serialVersionUID(它的作用和以前IO中的序列化流中UID是一样的,判断类是否一致用的)
3,重写方法
例:
public class test2 { public static void main(String[] args) { //把自定义的异常捕获 try { num("gg");} catch(mywqlExcepton e) { //打印追溯的错误信息 e.printStackTrace(); } finally { System.out.print("哈哈"); } } public static void num(String name) { if(name.equals("FQ")) { System.out.print("WQL LOVE"+name); }else { throw new mywqlExcepton("FQ说,你不love我了,拜拜了您");//手动抛出异常 }}} class mywqlExcepton extends RuntimeException{//继承运行时异常 private static final long serialVersionUID = 1L;//全局变量 //重写方法,没有动,它的父类继承Execption也是没有动其他方法 public mywqlExcepton() { super(); // TODO Auto-generated constructor stub } public mywqlExcepton(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public mywqlExcepton(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public mywqlExcepton(String message) { super(message); // TODO Auto-generated constructor stub } public mywqlExcepton(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
结果:
异常.mywqlExcepton: FQ说,你不love我了,拜拜了您 哈哈 at 异常.test2.num(test2.java:26) at 异常.test2.main(test2.java:8)
六,源码查看
1,RuntimeExecption解析
源码:
public class RuntimeException extends Exception {//继承了Exception static final long serialVersionUID = -7034897190745766939L;//序列号 public RuntimeException() { super();//掉用父类构造 } public RuntimeException(String message) {//带参构造,错误提示信息 super(message);//掉用父类构造并传入 } public RuntimeException(String message, Throwable cause) {//构造一个具有指定的详细信息和原因的新的throwable super(message, cause);//老样子 } public RuntimeException(Throwable cause) {//产生一个新的throwable super(cause);//一样 } protected RuntimeException(String message, Throwable cause,boolean enableSuppression,boolean writableStackTrace) { //构造具有指定的原因和详细消息的新throwable (cause==null ? null : cause.toString()) (它通常包含的类和详细消息 cause ) super(message, cause, enableSuppression, writableStackTrace); } }
2,Exception源码
源码:
public class Exception extends Throwable {//继承了Throwable顶级父类 static final long serialVersionUID = -3387516993124229948L;//序列号 public Exception() { super();//调用父类的构造 } //其他方法和RuntimeException是一样的,不说了, }
3,Throwable的源码
源码:
public class Throwable implements Serializable {//实现了Serializable标识接口 /** use serialVersionUID from JDK 1.0.2 for interoperability *//这个是这个类出现的版本时间,它在JDK1.0就出来了 private static final long serialVersionUID = -3042686055658047285L;//序列号 //太多了,不写了,比上面两个复杂 }
Error和其他异常类结构也和这个差不多,最终在做事情就是Throwable
Comments | NOTHING
Warning: Undefined variable $return_smiles in /www/wwwroot/wql_luoqin_ltd/wp-content/themes/Sakura/functions.php on line 1109