Java第九天(二)
异常
编译期异常自行处理即可;运行时异常向上抛出。
定义:在我们编写程序时难免会出现错误,Java中的异常机制为了提高程序的健壮性和容错性而存在。
Throwable
:Throwable类是Java语言中所有错误或异常的超类。
其已实现接口:Serializable
;直接子类:Error、Exception
;
除了RuntimeException
都是编译期的异常,编译期的异常我们必须处理,如果不处理就会编译失败。
运行期异常
定义:编译期没有异常,但在执行过程中产生的异常。
自行解决(try…catch语句块)
在try
内语句若未发生异常,则不会进入catch,反之则进入catch。
若try
中语句发生异常,则不会执行异常语句后的代码。
如果异常通过catch得到处理,catch{}
后面的代码与调用端的代码继续执行。
运行时发生异常的语句将不会在向下执行。
try{
可能发生异常的语句;
}catch(异常类型 异常变量名){
处理异常的代码;
}
打印异常信息(需要配合输出语句使用)
异常变量名.getMessage();
打印异常
异常变量名.printStackTrance();
打印出具体的异常类和异常信息(需要配合输出语句使用)
异常变量名.toString();
class Calculate{
public int devide(int a,int b) {
//使用try...catch
try {
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
} catch (Exception e) {
//1.使用getMessage方法
//System.out.println(e.getMessage());
//2.使用printStackTrace方法
//e.printStackTrace();
//3.使用toString方法
//System.out.println(e.toString());
}
}
}
public class ExceptionTest {
public static void main(String[] args) {
Calculate calculate = new Calculate();
calculate.devide(4, 0);
}
}
运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.exception.Calculate.devide(ExceptionTest.java:7)
at com.exception.ExceptionTest.main(ExceptionTest.java:17)
1.使用getMessage方法后
/ by zero
2.使用printStackTrace方法后
java.lang.ArithmeticException: / by zero
at com.exception.Calculate.devide(ExceptionTest.java:8)
at com.exception.ExceptionTest.main(ExceptionTest.java:21)
3.使用toString方法后
java.lang.ArithmeticException: / by zero
向上抛出(不处理会自动向上抛)
被调用的方法中发生了异常但未做处理,那么异常将被向上抛至调用的方法。
若调用方法不处理异常,那么调用语句后的代码将不会执行。
在处理时同样可以使用try...catch
语句处理。
class Calculate{
public void devide(int a,int b) {
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ExceptionTest {
public static void main(String[] args) {
Calculate calculate = new Calculate();
try {
calculate.devide(5,0);
} catch (Exception e) {
e.printStackTrace();
System.out.println("请检查计算公式!");
}
}
}
运行结果:
java.lang.ArithmeticException: / by zero
请检查计算公式!
at com.exception.Calculate.devide(ExceptionTest.java:5)
at com.exception.ExceptionTest.main(ExceptionTest.java:15)
try…catch…catch
可在try中定义两个或多个可能发生异常的语句,并在try后定义相关异常类型及异常变量名的catch。
try中异常语句的顺序与catch语句块的顺序无关。
class Calculate{
public void devide(int a,int b) {
int arr[] = new int[10];
//当打印数组第10位时,发生数组越界异常
System.out.println(arr[9]);
//被除数为0时,发生数学异常
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ExceptionTest {
public static void main(String[] args) {
Calculate calculate = new Calculate();
try {
calculate.devide(5,0);
} catch (ArithmeticException e) {
System.out.println("发生数学计算异常!");
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("发生数组越界异常!");
}
}
}
运行结果:
0
发生数学计算异常!
try…catch(instanceof比较)
try中有两个或多个可能会发生异常的语句时,可在catch的参数列表中使用异常父类Exception
并定义异常变量名,然后使用if语句与instanceof将异常变量与异常类进行比较。
try{
异常语句;
}catch(Exception 异常变量名){
if(异常变量名 instanceof 异常子类名){
处理代码;
}else{
处理代码;
}
}
class Calculate{
public void devide(int a,int b) {
int arr[] = new int[10];
System.out.println(arr[9]);
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ExceptionTest {
public static void main(String[] args) {
Calculate calculate = new Calculate();
try {
calculate.devide(5,0);
} catch (Exception e) {
if(e instanceof ArithmeticException) {
System.out.println("发生数学计算异常!");
}else if(e instanceof ArrayIndexOutOfBoundsException) {
System.out.println("发生数组越界异常!");
}else {
System.out.println("发生了其他异常!");
}
}
}
}
try…catch…finally
不论当try中是否发生异常,finally中的代码都会被执行。主要用来释放资源。
return后的局部变量的值将被保存下来,即使在未遇到下一个return同样局部变量之前改变了该局部变量的值,return局部变量的值也不会发生改变。只有在改变了局部变量的值后再次return该局部变量其值才会被改变。
int i = 10;
//此时返回的值为10
return i;
//即使改变了该局部变量的值,但因为是在return后作出改变,所以返回值不会发生变化
i = 20;
int i = 10;
//此时返回的值为10
return i;
//将该局部变量的值改变为20
i = 20;
//此时返回值为20
return i;
try{
代码;
}catch(Exception 异常变量名){
代码;
}finally{
代码;
}
class Calculate{
public void devide(int a,int b) {
int arr[] = new int[10];
System.out.println(arr[9]);
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ExceptionTest {
public static void main(String[] args) {
Calculate calculate = new Calculate();
try {
calculate.devide(5,0);
} catch (Exception e) {
if(e instanceof ArithmeticException) {
System.out.println("发生数学计算异常!");
}else if(e instanceof ArrayIndexOutOfBoundsException) {
System.out.println("发生数组越界异常!");
}else {
System.out.println("发生了其他异常!");
}
}finally {
System.out.println("无论何时都会执行的代码被执行!");
}
}
}
输出结果:
0
发生数学计算异常!
无论何时都会执行的代码被执行!
throw/throws关键字
如果一个方法没有捕获到一个运行期异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
class Calculate{
public void devide(int a,int b){
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ThrowException {
//这里使用了throws关键字
public static void main(String[] args) throws Exception{
Calculate calculate = new Calculate();
calculate.devide(4, 0);
}
}
运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.exception.Calculate.devide(ThrowException.java:5)
at com.exception.ThrowException.main(ThrowException.java:14)
class Calculate{
public void devide(int a,int b) throws Exception{
//这里使用if判断被除数是否为0
if(b == 0) {
throw new ArithmeticException();
}
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ThrowException {
public static void main(String[] args){
Calculate calculate = new Calculate();
try {
calculate.devide(4, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
java.lang.ArithmeticException
at com.exception.Calculate.devide(ThrowException.java:6)
at com.exception.ThrowException.main(ThrowException.java:19)
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
class Calculate{
//这里抛出了两个异常
public void devide(int a,int b) throws ArithmeticException,ArrayIndexOutOfBoundsException{
int arr[] = new int[10];
System.out.println(arr[10]);
int result = a/b;
System.out.println(a+"除"+b+"的结果为:"+result);
}
}
public class ThrowException {
public static void main(String[] args){
Calculate calculate = new Calculate();
try {
calculate.devide(4, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
编译期异常
try…catch自己处理
向上层抛出,直至有代码进行处理
自定义异常(运行期异常)
步骤:
①定义一个异常类
②继承RuntimeException类
③继承父类的构造器
使用:如果发生异常,throw new 自定义的异常类名(输出信息);
继承父类构造器快捷方式:Source→General Constructions from SuperClass
public class StockException extends RuntimeException {
public StockException() {
super();
// TODO Auto-generated constructor stub
}
public StockException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public StockException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public StockException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
新建一个类
public class ExceptionTest {
public static void main(String[] args) {
toBuy();
}
public static void toBuy() {
int kucun = 0;
if(kucun == 0) {
throw new StockException("库存不足!");
}
}
}
输出结果:
Exception in thread "main" com.exception.StockException: 库存不足!
at com.exception.ExceptionTest.Tobuy(ExceptionTest.java:15)
at com.exception.ExceptionTest.main(ExceptionTest.java:10)
错误(Error)
Error
是Throwable
的子类,标明程序出现了严重的问题,此问题程序无法解决。
错误都是以Error
为结尾。
final、finally、finalize区别
final
final可以修饰类、方法、成员变量。修饰类,该类不可被继承;修饰方法,该方法不可被重写;修饰成员变量,该成员变量的值不可被修改。
finally
finally与try…catch一同使用,finally语句块的内的代码一定会被执行。
finalize
当堆中的对象没有任何引用时,这个方法会被调用进行垃圾回收。