您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
【第7章:异常的基本概念】_异常的基本概念
发布时间:2020-12-18 15:12:15编辑:雪饮阅读()
异常的产生
这里除数为0,所以报了异常
public class Hello{
public static void main(String args[]){
int x=1;
int y=0;
System.out.println(x/y);
}
}
D:\>javac Hello.java
D:\>java Hello
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Hello.main(Hello.java:5)
异常的捕获
public class Hello{
public static void main(String args[]){
int x=1;
int y=0;
try{
System.out.println(x/y);
}
catch(ArithmeticException e){
System.out.println("出现异常了:"+e);
}
}
}
D:\>javac Hello.java
D:\>java Hello
出现异常了:java.lang.ArithmeticException: / by zero
finally关键字
从上面可以看到程序一旦出现了异常,程序就会被终止不会继续向下执行了,而finally关键字声明的代码块里面可以让即便程序遇到异常后也能执行一些语句。
public class Hello{
public static void main(String args[]){
int x=1;
int y=0;
try{
System.out.println(x/y);
}
catch(ArithmeticException e){
System.out.println("出现异常了:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
D:\>javac Hello.java
D:\>java Hello
出现异常了:java.lang.ArithmeticException: / by zero
不管你有没有异常我都会被执行
同时进行多个异常的捕获(多catch)
如果把计算参数提供给用户输入则上面的异常捕获就显得功能太单一
上面的异常捕获仅仅捕获了计算时除数为0的异常
public class Hello{
public static void main(String args[]){
try{
int x=Integer.parseInt(args[0]);
int y=Integer.parseInt(args[1]);
System.out.println(x/y);
}
catch(ArithmeticException e){
System.out.println("出现异常了:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
D:\>javac Hello.java
D:\>java Hello
不管你有没有异常我都会被执行
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Hello.main(Hello.java:4)
D:\>java Hello a b
不管你有没有异常我都会被执行
Exception in thread "main" java.lang.NumberFormatException: For input string: "a"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:447)
at java.lang.Integer.parseInt(Integer.java:497)
at Hello.main(Hello.java:4)
像是这样用户不输入参数时会报数组越界异常,参数不是数字时候又会报数字格式化异常。
这个时候就需进行多个异常的捕获了。
public class Hello{
public static void main(String args[]){
try{
int x=Integer.parseInt(args[0]);
int y=Integer.parseInt(args[1]);
System.out.println(x/y);
}
catch(ArithmeticException e){
System.out.println("算术异常:"+e);
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:"+e);
}
catch(NumberFormatException e){
System.out.println("数字格式化异常:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
D:\>javac Hello.java
D:\>java Hello
数组越界异常:java.lang.ArrayIndexOutOfBoundsException: 0
不管你有没有异常我都会被执行
D:\>java Hello a b
数字格式化异常:java.lang.NumberFormatException: For input string: "a"
不管你有没有异常我都会被执行
打印堆栈跟踪
在出现异常时候可以通过异常实例来获取堆栈跟踪,从而快速找到问题代码所在
public class Hello{
public static void main(String args[]){
try{
int x=Integer.parseInt(args[0]);
int y=Integer.parseInt(args[1]);
System.out.println(x/y);
}
catch(ArithmeticException e){
e.printStackTrace();
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:"+e);
}
catch(NumberFormatException e){
System.out.println("数字格式化异常:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
D:\>javac Hello.java
D:\>java Hello 1 0
java.lang.ArithmeticException: / by zero
at Hello.main(Hello.java:6)
不管你有没有异常我都会被执行
Exception
Exception异常是所有异常的始祖类,当一个个去捕获异常比较麻烦的时候可以直接用Exception来捕获。
public class Hello{
public static void main(String args[]){
try{
int x=Integer.parseInt(args[0]);
int y=Integer.parseInt(args[1]);
System.out.println(x/y);
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:"+e);
}
catch(NumberFormatException e){
System.out.println("数字格式化异常:"+e);
}
catch(Exception e){
System.out.println("其它异常:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
D:\>javac Hello.java
D:\>java Hello 1 0
其它异常:java.lang.ArithmeticException: / by zero
不管你有没有异常我都会被执行
异常捕获的顺序问题
上面Exception捕获是放在最后的,它的捕获粒度最粗,有一个规定就是捕获粒度越细的要越靠前,否则会导致编译错误。
public class Hello{
public static void main(String args[]){
try{
int x=Integer.parseInt(args[0]);
int y=Integer.parseInt(args[1]);
System.out.println(x/y);
}
catch(Exception e){
System.out.println("其它异常:"+e);
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:"+e);
}
catch(NumberFormatException e){
System.out.println("数字格式化异常:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
D:\>javac Hello.java
Hello.java:11: 已捕捉到异常 java.lang.ArrayIndexOutOfBoundsException
catch(ArrayIndexOutOfBoundsException e){
^
Hello.java:14: 已捕捉到异常 java.lang.NumberFormatException
catch(NumberFormatException e){
^
2 错误
这是因为Exception放在最前面进行捕获时候捕获了所有异常,而后面细粒度的异常捕获本就属于Exception,所以会出现异常重复捕获。
Throwable
Exception是异常的始祖类,而Exception类下面有两个大的分支。
一个是Throwable异常,该异常负责.java文件中编码异常的捕获。
另外一个是Error异常,该异常是负责java的JVM虚拟机异常捕获。
例如当前目录下没有aaa.class的java类文件,那么执行Java命令如
D:\>java aaa
Exception in thread "main" java.lang.NoClassDefFoundError: aaa
Caused by: java.lang.ClassNotFoundException: aaa
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
Could not find the main class: aaa. Program will exit.
像是这样的异常就是java的JVM虚拟机异常
这类异常肯定是在程序代码中不能捕获到的。。。
既然如此,那么程序代码中捕获异常的最粗粒度也可以用Throwable替换Exception
public class Hello{
public static void main(String args[]){
try{
int x=Integer.parseInt(args[0]);
int y=Integer.parseInt(args[1]);
System.out.println(x/y);
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常:"+e);
}
catch(NumberFormatException e){
System.out.println("数字格式化异常:"+e);
}
catch(Throwable e){
System.out.println("其它异常:"+e);
}
finally{
System.out.println("不管你有没有异常我都会被执行");
}
}
}
但是这种异常是不建议的,仅仅因为语义上的不工整。。。
关键字词:java,异常