异常的注意事项
1.多个异常使用捕获应该怎样处理?
- 1.多个异常分别处理
- 2.多个异常一次捕获,多次处理
- 3.多个异常一次捕获一次处理
package demo02;
import java.util.List;
public class Demo01 {
public static void main(String[] args) {
//1.多个异常分别处理
try{
int[] arr = {1,2,3};
System.out.println(arr[3]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
try{
List<Integer> list = List.of(1,2,3);
System.out.println(list.get(3));
}catch (IndexOutOfBoundsException e){
System.out.println(e);
}
//2.多个异常一次捕获,多次处理
/*一个try多个catch注意事项:
* catch里边定义的异常变量,如果有父子关系,那么子类的异常变量必须写在上面,否则就会报错
* ArrayIndexOutOfBoundsException extend IndexOutOfBoundsException*/
try{
int[] arr = {1,2,3};
System.out.println(arr[3]);
List<Integer> list = List.of(1,2,3);
System.out.println(list.get(3));
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}catch (IndexOutOfBoundsException e){
System.out.println(e);
}
//3.多次异常处理,一次捕获,一次处理
try{
int[] arr = {1,2,3};
System.out.println(arr[3]);
List<Integer> list = List.of(1,2,3);
System.out.println(list.get(3));
}catch (IndexOutOfBoundsException e){
System.out.println(e);
}
}
}
2.finally中有return语句
如果finally中有return语句,永远返回finally中的结果,避免该情况。
public class Demo02 {
public static void main(String[] args) {
int a = getA();
System.out.println(a);
}
private static int getA() {
int a = 10;
try{
return a;
}catch (Exception e){
System.out.println(e);
}finally {
a = 100;
return a;
}
}
}
3.子父类的异常:
子父类的异常:
父类方法抛出多个异常:子类重写父类方法时,抛出和父类相同的异常,抛出父类异常的子类,不抛出异常
父类方法没有抛出异常:子类重写父类该方法时也不可抛出异常,此时子类产生该异常,只能捕获处理,不能抛出
总结:
父类异常是啥样,子类异常就是啥样
public class Fu {
public void show01() throws NullPointerException,ClassCastException{}
public void show02() throws IndexOutOfBoundsException{}
public void show03() throws IndexOutOfBoundsException{}
public void show04() {}
}
class Zi extends Fu{
//子类重写父类方法时,抛出和父类相同的异常
public void show01() throws NullPointerException,ClassCastException{}
//子类重写父类方法时,抛出父类异常的子类
public void show02() throws ArrayIndexOutOfBoundsException{}
//子类重写父类方法时,不抛出异常
public void show03(){}
/*父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常
* 只能进行捕获处理,不能声明抛出*/
public void show04(){
try{
throw new Exception("编译期异常");
}catch (Exception e){
e.printStackTrace();
}
}
}
自定义异常类
自定义异常类:
- java提供的异常类,不够我们使用,需要自己定义一些异常类
格式:
- public class XXXException extends Exception | RuntimeException{
- 添加一个空参构造;
- 添加一个带异常信息的构造方法
- }
注意:
- 1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
- 2.自定义异常类,必须得继承Exception或者RuntimeException
-
继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,使用throws或者try..catch
-
继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给JVM中断处理即可。
public class RegisterException extends Exception{
//添加一个空参的构造方法
public RegisterException(){}
//添加一个带异常信息的构造方法
//查看源码发现,所有的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理这个异常信息。
public RegisterException(String s){
super(s);
}
}
自定义异常类的使用
package demo02;
import java.util.Scanner;
要求:我们模拟注册操作,如果用户名已存在,则抛出异常并提醒:亲,该用户名已经被注册
* 分析:
* 1.使用数组保存已经注册过的用户名(数据库)
* 2.使用Scanner获取用户输入的注册的用户名(前端,页面)
* 3.定义一个方法,对用户输入的用户名进行判断
* 遍历存储以及注册过用户名的数组,获取每一个用户名
* 使用获取到的用户名和用户输入的用户名比较
* true:用户名已经存在,抛出异常,告知用户“该用户名已经被注册”
* false:继续遍历比较
* 如果循环结束,还没找到重复的用户名,提示用户"恭喜,注册成功!"
*
* 注意:
* throws抛出时,RegisterException继承的是Exception类,而且不需要更改什么
* try...catch捕获时,需要在if中return一下,使方法结束,否则后续的注册成功还是会出现
* 若将DemoRegisterException继承RuntimeException类,则直接throw,不需要处理,JVM会进行中断操作
* */
public class DemoRegisterException {
// 1.使用数组保存已经注册过的用户名(数据库)
static String[] usernames = {"张三","李四","王五"};
public static void main(String[] args) throws RegisterException {
// 2.使用Scanner获取用户输入的注册的用户名(前端,页面)
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要注册的用户名:");
String username = sc.next();
checkUsername(username);
}
// 3.定义一个方法,对用户输入的用户名进行判断
public static void checkUsername(String username) throws RegisterException {
//遍历存储以及注册过用户名的数组,获取每一个用户名
for (String user : usernames) {
if (user.equals(username)){
//true:用户名已经存在,抛出异常,告知用户“该用户名已经被注册”
throw new RegisterException("抱歉,该用户名已经被注册");
}
}
// 如果循环结束,还没找到重复的用户名,提示用户"恭喜,注册成功!"*/
System.out.println("恭喜,注册成功!");
}
}