Java基础__Java中异常处理那些事
一、Exception 类的层次
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Error 用来指示运行时环境发生的错误。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
JAVA异常与异常处理提示:传送门
测试
1、抛出java.lang.ArithmeticException异常
package Cynical_Gary; public class Gary_Text { public static void main(String[] args) { System.out.println("-1.0/0 = "+(-1.0/0)); //演示负浮点数除以0 System.out.println("+1.0/0 = "+(+1.0/0)); //演示正浮点数除以0 try { //捕捉异常 System.out.println("-1.0/0="+(-1/0)); //演示负整数除以0 }catch(Exception e) { System.out.println("抛出异常:"+e.getMessage()); } System.out.println("+1/0="+(+1/0)); //演示正整数除以0 System.out.println("输出结束。"); } } /* 输出: Exception in thread "main" java.lang.ArithmeticException: / by zero at Cynical_Gary.Gary_Text.main(Gary_Text.java:13) -1.0/0 = -Infinity +1.0/0 = Infinity 抛出异常:/ by zero */
2、抛出java.lang.StringIndexOutOfBoundsException异常
package Cynical_Gary; import java.util.Arrays; public class Gary_Text { public static void main(String[] args) { int array[] = new int[5]; Arrays.fill(array, 6); for(int i=0;i<6;i++) { System.out.println("array["+i+"]"+array[i]); } } } /* 输出: array[0]6 array[1]6 array[2]6 array[3]6 array[4]6 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Cynical_Gary.Gary_Text.main(Gary_Text.java:11) */
3、抛出java.lang.NullPointerException异常
package Cynical_Gary; public class Gary_Text { public static void main(String[] args) { String string = null; System.out.println(string.toLowerCase()); } } /* 输出: Exception in thread "main" java.lang.NullPointerException at Cynical_Gary.Gary_Text.main(Gary_Text.java:7) */
4、抛出java.lang.ClassNotFoundException异常
package Cynical_Gary; public class Gary_Text { public static void main(String[] args) { try{ Class.forName("com.mysql.jdbc.Driver"); //加载MySQL驱动程序 }catch(ClassNotFoundException e){ //捕获异常 e.printStackTrace(); //打印堆栈信息 } } } /* 输出: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver */
5、抛出java.lang.IllegalAccessException异常
package Cynical_Gary; import java.lang.reflect.Field; public class Gary_Text { public static void main(String[] args) { Class<?>clazz = String.class; //获得代表String类的类对象 Field[] fields = clazz.getDeclaredFields(); //获得String类的所有域 for(Field field:fields) { //遍历所有域 try { System.out.println(field.getInt("hash")); //输出hash的值 }catch(IllegalArgumentException e) { //捕获IllegalArgumentException异常 e.printStackTrace(); }catch(IllegalAccessException e) { //捕获IllegalAccessException异常 e.printStackTrace(); } } } } /* 输出: java.lang.IllegalAccessException: Class Cynical_Gary.Gary_Text can not access a member of class java.lang.String with modifiers "private final" at sun.reflect.Reflection.ensureMemberAccess(Unknown Source) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(Unknown Source) at java.lang.reflect.AccessibleObject.checkAccess(Unknown Source) at java.lang.reflect.Field.getInt(Unknown Source) at Cynical_Gary.Gary_Text.main(Gary_Text.java:12) */
6、抛出java.io.FileNotFoundException异常
package Cynical_Gary; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class Gary_Text { public static void main(String[] args) { FileInputStream fis = null; //创建一个文件输入流对象 try { File file = new File("d\\kira.txt"); //创建一个文本对象 fis = new FileInputStream(file); //初始化文件输入流对象 }catch(FileNotFoundException e) { //捕获异常 e.printStackTrace(); }finally { try { fis.close(); //释放资源 }catch(IOException e) { e.printStackTrace(); } } } } /* 输出: java.io.FileNotFoundException: d\kira.txt (系统找不到指定的路径。) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(Unknown Source) at java.io.FileInputStream.<init>(Unknown Source) at Cynical_Gary.Gary_Text.main(Gary_Text.java:14) Exception in thread "main" java.lang.NullPointerException at Cynical_Gary.Gary_Text.main(Gary_Text.java:19) */
7、抛出java.lang.ClassNotFoundException异常
package Cynical_Gary; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class Gary_Text { public static void main(String[] args) { String URL = "jdbc:mysql://localhost:3306/db_database"; //MySQL数据库的URL String DRIVER = "com.mysql.jdbc.Driver"; //数据库的用户名 String USERNAME = "mr"; //数据库的用户名 Connection connection = null; try { Class.forName(DRIVER); //加载驱动 connection = DriverManager.getConnection(URL,USERNAME,""); //建立连接 }catch(SQLException e) { e.printStackTrace(); }catch(ClassNotFoundException e) { e.printStackTrace(); }finally { try { connection.close(); }catch(SQLException e){ e.printStackTrace(); } } } } /* 输出: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at Cynical_Gary.Gary_Text.main(Gary_Text.java:16) Exception in thread "main" java.lang.NullPointerException at Cynical_Gary.Gary_Text.main(Gary_Text.java:24) 这里需要将MySQL数据库驱动包配置到构建路径中,否则将不能抛出SQLException异常,而是抛出ClassNotFoundException异常 */
8、抛出java.lang.UnsupportedOperationException异常
package Cynical_Gary; public class Gary_Text { public static void throwException(){ throw new UnsupportedOperationException("此方法尚未实现"); //抛出异常 } public static void main(String[] args) { Gary_Text.throwException(); } } /* 输出: Exception in thread "main" java.lang.UnsupportedOperationException: 此方法尚未实现 at Cynical_Gary.Gary_Text.throwException(Gary_Text.java:6) at Cynical_Gary.Gary_Text.main(Gary_Text.java:9) */
9、抛出java.lang.ClassNotFoundException异常
package CynicalGary; public class Gary_Text { public static void throwsException() throws ClassNotFoundException{ //抛出异常 Class.forName("com.mysql.jdbc.Driver"); } public static void main(String[] args) { try { //捕获异常 Gary_Text.throwsException(); //调用抛出异常 }catch(ClassNotFoundException e) { e.printStackTrace(); } } } /* 输出 java.lang.ClassNotFoundException: com.mysql.jdbc.Driver at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at CynicalGary.Gary_Text.throwsException(Gary_Text.java:5) at CynicalGary.Gary_Text.main(Gary_Text.java:10) */
10、抛出CynicalGary(自定义类).DivideZeroException异常
package CynicalGary; public class DivideZeroException extends ArithmeticException{ //自定义异常类 public DivideZeroException() { //实现默认构造方法 } public DivideZeroException(String msg) { //实现有输出信息的构造方法 super(msg); } }
package CynicalGary; import java.util.Arrays; public class Gary_Text { public static void main(String[] args) { int[] array = new int[5]; Arrays.fill(array, 5); for(int i=4;i>-1;i--) { if(i==0) { throw new DivideZeroException("除零异常"); } System.out.println("array["+i+"]/"+i+"="+array[i]/i); } } } /* 输出 array[4]/4=1 array[3]/3=1 array[2]/2=2 array[1]/1=5 Exception in thread "main" CynicalGary.DivideZeroException: 除零异常 at CynicalGary.Gary_Text.main(Gary_Text.java:12) */
11、抛出java.lang.ClassNotFoundException:异常
package CynicalGary; public class Gary_Text { public static void main(String[] args) { try { System.out.println("进入try语句块"); Class<?>clazz = Class.forName(""); System.out.println("离开try语句块"); }catch(ClassNotFoundException e) { System.out.println("进入catch语句块"); e.printStackTrace(); System.out.println("离开catch语句块"); }finally { System.out.println("进入finally语句块"); } } } /* 输出 进入try语句块 进入catch语句块 java.lang.ClassNotFoundException: at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at CynicalGary.Gary_Text.main(Gary_Text.java:7) 离开catch语句块 进入finally语句块 */
捕获单个异常,Java中捕获异常是通过try...catch...dinally语句来完成的,其中try语句块是必须的,catch和finally语句块可以选择一个或两个。try语句块用来放置可能出现问题的语句,catch语句块用来放置异常后执行的代码,finally语句块用来放置无论是否发送异常都需要执行的代码
12、抛出java.lang.ClassNotFoundException异常
package CynicalGary; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class Gary_Text { private static String URL = "jdbc:mysql://localhost:3306/db_database";//数据库URL private static String DRIVER = "com.mysql.jdbc.Driver"; //数据库驱动 private static String USERNAME ="Gary"; //用户 private static String PASSWORD = "123456"; //密码 private static Connection conn; public static Connection getConnextion() { try { Class.forName(DRIVER); conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); //建立连接 return conn; }catch(ClassNotFoundException e) { e.printStackTrace(); }catch(SQLException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { Gary_Text.getConnextion(); } } /* 输出 java.lang.ClassNotFoundException: com.mysql.jdbc.Driver at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at CynicalGary.Gary_Text.getConnextion(Gary_Text.java:15) at CynicalGary.Gary_Text.main(Gary_Text.java:27) */
异常方法
public String getMessage() 返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。 public Throwable getCause() 返回一个Throwable 对象代表异常原因。 public String toString() 使用getMessage()的结果返回类的串级名字。 public void printStackTrace() 打印toString()结果和栈层次到System.err,即错误输出流。 public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 public Throwable fillInStackTrace() 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。
二、捕获异常
单重捕获异常
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
try { // 程序代码 }catch(ExceptionName e1) { //Catch 块 }
Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。
多重捕获块
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获。
多重捕获块的语法如下所示:
try{ // 程序代码 }catch(异常类型1 异常的变量名1){ // 程序代码 }catch(异常类型2 异常的变量名2){ // 程序代码 }catch(异常类型2 异常的变量名2){ // 程序代码 }
上面的代码段包含了 3 个 catch块。
可以在 try 语句后面添加任意数量的 catch 块。
如果保护代码中发生异常,异常被抛给第一个 catch 块。
如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
如果不匹配,它会被传递给第二个 catch 块。
如此,直到异常被捕获或者通过所有的 catch 块。
三、throws/throw 关键字:
java中的异常抛出通常使用throw和throws关键字来实现。
throw ----将产生的异常抛出,是抛出异常的一个动作。
一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。如:
语法:throw (异常对象),如:
public static void main(String[] args) { String s = "abc"; if(s.equals("abc")) { throw new NumberFormatException(); } else { System.out.println(s); } //function(); }
运行结果:
Exception in thread "main" java.lang.NumberFormatException
at test.ExceptionTest.main(ExceptionTest.java:67)
throws----声明将要抛出何种类型的异常(声明)。
语法格式:
public void 方法名(参数列表) throws 异常列表{ //调用会抛出异常的方法或者: throw new Exception(); }
throw与throws的比较
1、throws出现在方法函数头;而throw出现在函数体。
2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
四、finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
try{ // 程序代码 }catch(异常类型1 异常的变量名1){ // 程序代码 }catch(异常类型2 异常的变量名2){ // 程序代码 }finally{ // 程序代码 }
五、自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
感谢:
菜鸟教程:传送门
Java常见异常和解决办法:传送门