在JAVA中异常就是一个类,产生异常就是创建异常对象并抛出一个异常对象。JAVA处理异常的方式是中断处理。
参考:java-异常体系
一、异常概述
异常体系- 异常:一类是 IOException,其中 IOException 及其子类异常又被称作受查异常(必须在编译期处理)。另一类是 RuntimeException,RuntimeException 被称作非受查异常。
-
错误:程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
异常处理原理
二、异常处理
【1】throw 抛出的运行时异常对象,程序员可以不处理,默认交给JVM处理(打印异常,中断处理)。
public class Demo03Throw {
public static void main(String[] args) {
int[] arr = null;
int e = getElement(arr,3);
System.out.println(e);
}
/*
* NullPointerException是一个运行期异常,我们不用处理,默认交给JVM处理
*/
public static int getElement(int[] arr,int index){
if(arr == null){
throw new NullPointerException("传递的数组的值是null");
}
int ele = arr[index];
return ele;
}
}
【2】 当方法内部抛出异常对象的时候,必须处理这个异常对象,可以使用throws声明这个异常对象,将异常对象抛出给方法的调用者处理,调用者可以将异常继续throws,最终甩锅给JVM处理。缺陷就是后续代码不能执行。
import java.io.FileNotFoundException;
import java.io.IOException;
public class Demo05Throws {
public static void main(String[] args) throws FileNotFoundException,IOException {
readFile("c:\\a.tx");
System.out.println("后续代码");
}
public static void readFile(String fileName) throws FileNotFoundException,IOException{
if(!fileName.equals("c:\\a.txt")){
throw new FileNotFoundException("传递的文件路径不是c:\\a.txt");
}
if(!fileName.endsWith(".txt")){
throw new IOException("文件的后缀名不对");
}
System.out.println("路径没有问题,读取文件");
}
}
【3】当方法内部抛出异常对象的时候,必须处理这个异常对象,可以使用try处理这个异常,不甩锅。后续代码会继续执行。 后续代码会继续执行。后续代码会继续执行。
import java.io.IOException;
public class Demo01TryCatch {
public static void main(String[] args) {
try{
//可能产生异常的代码
readFile("d:\\a.tx");
System.out.println("资源释放");
}catch (IOException e){
/* Throwable类中定义了3个异常处理的方法
String getMessage() 返回此 throwable 的简短描述。
String toString() 返回此 throwable 的详细消息字符串。
void printStackTrace() JVM打印异常对象,默认此方法,打印的异常信息是最全面的*/
e.printStackTrace();
}finally{
//永远返回finally中的结果。避免return语句。
System.out.println("资源释放");
}
System.out.println("后续代码");
}
public static void readFile(String fileName) throws IOException {
if(!fileName.endsWith(".txt")){
throw new IOException("文件的后缀名不对");
}
System.out.println("路径没有问题,读取文件");
}
}
父子类处理异常:父类异常时什么样,子类异常就什么样。
- 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
- 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。
package com.itheima.demo03.Exception;
public class Fu {
public void show01() throws NullPointerException,ClassCastException{}
public void show02() throws IndexOutOfBoundsException{}
public void show03() throws IndexOutOfBoundsException{}
public void show04() throws Exception {}
}
class Zi extends Fu{
//子类重写父类方法时,抛出和父类相同的异常
public void show01() throws NullPointerException,ClassCastException{}
//子类重写父类方法时,抛出父类异常的子类
public void show02() throws ArrayIndexOutOfBoundsException{}
//子类重写父类方法时,不抛出异常
public void show03() {}
/*
*父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。
*/
//public void show04() throws Exception{}
//此时子类产生该异常,只能捕获处理,不能声明抛出
public void show04() {
try {
throw new Exception("编译期异常");
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
package com.itheima.demo04.MyException;
/*
自定义异常类:
java提供的异常类,不够我们使用,需要自己定义一些异常类
格式:
public class XXXExcepiton extends Exception | RuntimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
注意:
1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
2.自定义异常类,必须的继承Exception或者RuntimeException
继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch
继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理)
*/
public class RegisterException extends /*Exception*/ RuntimeException{
//添加一个空参数的构造方法
public RegisterException(){
super();
}
/*
添加一个带异常信息的构造方法
查看源码发现,所有的异常类都会有一个带异常信息的构造方法,
方法内部会调用父类带异常信息的构造方法,
让父类来处理这个异常信息
*/
public RegisterException(String message){
super(message);
}
}
应用
import java.util.Scanner;
public class Demo02RegisterException {
// 1.使用数组保存已经注册过的用户名(数据库)
static String[] usernames = {"张三","李四","王五"};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要注册的用户名:");
String username = sc.next();
checkUsername(username);
}
public static void checkUsername(String username) {
for (String name : usernames) {
if(name.equals(username)){
//抛出运行期异常,无需处理,交给JVM处理,中断处理
throw new RegisterException("亲,该用户名已经被注册");
}
}
System.out.println("恭喜您,注册成功!");
}
}
网友评论