Java 的异常类
异常的体系
- Throwable
- Error
- Exception
- RuntimeException
如果程序没有处理异常, JVM 自行处理, 把异常的名称和信息, 打印在控制台上.
异常的2种处理方式
- try catch finally
- try catch
- try catch finally
- try finally
- throws
public class Demo1_Exception {
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
int x;
try{
x = demo1.div(10,0);
} catch (ArithmeticException e){
System.out.println(e.getClass());
System.out.println("test");
}finally {
System.out.println("最后执行了吗");
}
}
}
class Demo1 {
public int div (int a, int b){
return a/b;
}
}
public class Demo2_Exception {
public static void main(String[] args) {
int a = 0;
int b = 10;
int[] arr = {1, 2, 3};
int x ;
arr = null;
try {
// x = b / a;
System.out.println(arr[10]);
} catch (ArithmeticException e){
System.out.println(e.getClass());
} catch (IndexOutOfBoundsException e){
System.out.println(e.getClass());
} catch (Exception e){
System.out.println("有异常");
}
}
}
public class Demo3_Exception {
public static void main(String[] args) {
try {
System.out.println(10/0);
} catch (ArithmeticException | IndexOutOfBoundsException e){
System.out.println("Exception");
}
}
}
异常throwable 的方法
- String getMessage() 获取异常信息
- String toString() 获取异常类和异常信息
- void printStackTrace() 获取异常类和异常信息, 异常在程序出现的位置
public class Demo3_Exception {
public static void main(String[] args) {
try {
System.out.println(10/0);
} catch (ArithmeticException | IndexOutOfBoundsException e){
System.out.println(e.getMessage());
System.out.println(e.toString());
e.printStackTrace();
}
}
}
方法上的2种异常
- RuntimeException 运行时异常, 不需要在方法向上抛出, 使用的时候也不需要在使用的方法上向上抛出
- 非RuntimeException 的异常, 必须在方法上向上抛出, 使用方法时也必须向上抛出异常
import lombok.Getter;
import lombok.Setter;
public class Person {
public Person(){}
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Getter
@Setter
private String name;
@Getter
private int age;
public void setAge(int age) {
if(age < 1 || age > 150){
throw new RuntimeException ("年龄非法");
}
this.age = age;
}
}
import lombok.Getter;
import lombok.Setter;
public class Person {
public Person(){}
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Getter
@Setter
private String name;
@Getter
private int age;
public void setAge(int age) throws Exception{
if(age < 1 || age > 150){
throw new Exception ("年龄非法");
}
this.age = age;
}
}
public class Demo4_Exception {
public static void main(String[] args) throws Exception{
Person p = new Person();
p.setAge(-12);
System.out.println("MM");
}
}
throws 和 throw 区别
- throws
- 用在方法声明后, 跟的是异常类名
- 跟以跟多个类名, 用逗号隔开
- 表示抛出异常, 由该方法的调用者处理
- throw
- 用在方法内, 跟的是异常对象名
- 只能抛出一个异常对象名
- 表示抛出异常, 由方法体内的语句处理
finally
- finally 的特点
- 被finally 控制的语句一定会执行
- 特殊情况: 在执行finally 前 JVM 退出了(如System.exit(0))
- finally 的作用
- 用于释放资源, 在IO 操作和数据库操作中会见到
- return 的区别 return 执行后, 如果有finally 则执行finally 类
public class Demo5_Exception {
public static void main(String[] args) {
try {
System.out.println(1/0);
} catch (Exception e){
System.out.println("异常");
} finally {
System.out.println("最后一定执行");
}
}
}
final finally finalize 区别
- final
- final 可以修饰类, 但不能被继承
- 修饰方法不能被重写
- 修饰变量只能赋值一次
- finally
- try catch finally 体系中的一个语句, 不能单独使用
- finalize
- 当垃圾回收器确定不存在该对象的更多引用时, 对象回收器则调用此方法
public class Demo6_Exception {
public static void main(String[] args) {
System.out.println(demo1());
}
public static int demo1(){
int x = 10;
try {
x = 20;
System.out.println(1/0);
return x;
} catch (Exception e){
x = 30;
return x;
} finally {
x = 40;
}
}
}
x 会返回30, return 把x=30装箱返回回去
自定义异常
- 为什么需要定义异常类
- 可通过异常类名字即可知道错误在哪
- 异常使用
- 自定义异常类, 继承Exception
- 在方法中使用异常类
- 调用方法时处理异常类(try catch finally)或直接抛出
public class OutOfAgeException extends Exception {
public OutOfAgeException() {
super();
}
public OutOfAgeException(String message) {
super(message);
}
public OutOfAgeException(String message, Throwable cause) {
super(message, cause);
}
public OutOfAgeException(Throwable cause) {
super(cause);
}
protected OutOfAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
import com.lizicai.exception.OutOfAgeException;
import lombok.Getter;
import lombok.Setter;
public class Person {
public Person(){}
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Getter
@Setter
private String name;
@Getter
private int age;
public void setAge(int age) throws Exception{
if(age < 1 || age > 150){
throw new OutOfAgeException("年龄异常");
}
this.age = age;
}
}
public class Demo7_Exception {
public static void main(String[] args) throws Exception {
Person p = new Person();
p.setAge(-10);
}
}
异常
- 子类重写父类方法时, 子类的方法必须抛出相同的异常或父类异常的子类( 子类不能比父类坏的更多 )
- 如果父类抛出多个异常, 子类重写父类时, 只能抛出相同的异常或异常的子类, 子类不能抛出父类没有的异常
- 如果重写方法没有异常抛出, 那么子类的方法绝对不可以抛出异常, 如果子类方法内有异常发生, 那么子类能try catch,不能throws
练习
- 输入一个整数
- 超出整数范围则提示过大, 重新输入整数
- 输入小数则提示小数, 重新输入整数
- 输入字符等, 则提示非法字符, 请重新输入整数
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class Demo8_Exception {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = null;
BigInteger bigInteger = null;
BigDecimal bigDecimal = null;
int scInt = 0;
System.out.println("请输入一个整数:");
while (sc.hasNext()){
str = sc.nextLine();
try {
scInt = Integer.parseInt(str);
System.out.println(Integer.toBinaryString(scInt));
break;
} catch (Exception e){
try {
bigInteger = new BigInteger(str);
System.out.println("过大的整数, 请重新输入整数");
} catch (NumberFormatException e2){
try{
bigDecimal = new BigDecimal(str);
System.out.println("输入的小数, 请重新输入整数");
} catch (Exception e3){
System.out.println("输入的非法字符, 请重新输入整数");
}
}
}
}
}
}