| 异常:程序在运行时发生错误。 |
| 异常基本语法 |
public class ExceptionTest {
public static void main(String[] args) {
int[] data = {1, 2, 3};
System.out.println("before");
try {
// 可能会出现异常的地方
System.out.println(data[100]);
}catch (ArrayIndexOutOfBoundsException e){
//打印出现异常调用的栈
e.printStackTrace();
System.out.println("异常产生了");
}
System.out.println("after");
}
}
| 异常的种类有很多,我们要根据不同的业务场景来决定; 对于比较严重的场景应该让程序直接崩溃; 其他的场景可以选择记录错误日志,通过监控报警程序及时通知,可恢复的场景选择重试; |
| 关于---调用栈 方法之间存在相互的调用关系。 在JVM中有一块内存空间称为“虚拟机栈”,专门为存储方法之间的调用关系,当代吗中出现异常 ,我们可以调用e这个对象的printStackTrace()就可以打印异常位置和原因。 e.printStackTrace(); 查看出现异常代码的调用栈。 “e”就是异常对象,e前面是类名称,起个什么名字都一样。 |
public class ExceptionTest {
public static void main(String[] args) {
int[] data = {1, 2, 3};
System.out.println("before");
data=null;
try {
System.out.println(data[100]);
System.out.println("after");
}catch (ArrayIndexOutOfBoundsException e){
//打印出现异常调用的栈
e.printStackTrace();
}
System.out.println("after try catch");
}
}
public class ExceptionTest {
public static void main(String[] args) {
int[] data = {1, 2, 3};
try {
System.out.println("before");
data=null;
System.out.println(data[100]);
System.out.println("after");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("这是个数组下标越界异常");
//打印出现异常调用的栈
e.printStackTrace();
}catch (NullPointerException e){
System.out.println("这个是空指针异常");
e.printStackTrace();
}
System.out.println("after try catch");
}
}
由于Exception 类是所有异常类的父类,因此可以用这个类型捕获所有异常。
如果我们catch代码块中捕获到了Exception这个类型,就可以接收到所有的异常类型。
备注:catch进行类型匹配的时候,不光会匹配相同类型的异常对象,也会捕捉目标异常类型的子类对象,如刚才的代码,NullPointException 和ArrayIndexOutBoundException都是Exception的子类,因此都能被捕获到。
public class ExceptionTest { public static void main(String[] args) { int[] data = {1, 2, 3}; try { System.out.println("before"); data=null; System.out.println(data[100]); System.out.println("after"); }catch (Exception e){ e.printStackTrace(); } System.out.println("after try catch"); } }
finally 表示最后的善后工作,例如释放资源,方法的关闭操作。
finally代码块无论异常有没有都会执行
public class ExceptionTest { public static void main(String[] args) { int[] data = {1, 2, 3}; try { System.out.println("before"); data=null; System.out.println(data[100]); System.out.println("after"); }catch (Exception e){ e.printStackTrace(); }finally { System.out.println("finally code"); } } }public class MyArrayList { public static void main(String[] args) { int ret=test(); System.out.println(ret); } public static int test() { int[] data = {1, 2, 3}; try { data[100]=10; return 10; }catch (Exception e){ e.printStackTrace(); return 20; }finally { System.out.println("finally code"); return 30; } } }finally代码块中不要写返回值
使用try负责回收资源
将Scanner对象在try的()中创建,就能保证在try执行完毕后自动调用Scanner的close方法
| 异常处理流程 |
java中一切都是类,异常也是类,因此Catch代码块只能捕获相应的异常“类型”,
好我再加上一个Catch
好这时候就正确输出了。说明我们捕获到了匹配的异常代码。。
如果嫌多个catch太麻烦,直接使用异常父类-Exception:
catch(Exception e){}
就可以了,这时候不管什么异常都能捕获,但是不知道是什么异常。
自己抛出的异常:
如果异常没有被处理,JVM就是最后的背锅侠,扔给JVM之后程序退出。
异常说明
我们在处理异常的时候,通常希望知道这段代码中究竟会出现那些可能异常。
我么可以使用thorws关键字,把可能抛出的异常显式的标注在定义的位置,从而提醒调用者
要注意捕获这些异常
public class ExceptionTest { public static void main(String[] args) { System.out.println(fun()); } public static int fun(){ try{ return 10; }finally { return 20; } } }output:20
注意:finally执行的时机在方法返回之前(try或者catch中如果有return会在这个return之前执行finally),但是如果finally中也存在return语句,那么就会执行finally中的return,从而不会执行到try中原有的return。一般我们不建议在finally中写return(被编译器当做一个警告)
| java异常体系 |
异常之家
顶层的Throwable 派生出两个重要子类,Error和Exception
其中Error 指的是java运行时内部错误和资源耗尽错误,应用程序不抛出此类异常,这种内部错误一旦出现,处理告知用户并使程序员终止之外,在无能为力。
OutofMemoryError堆内存溢出 StackOverflowError栈溢出
Exception是我们程序员所使用的的异常的父类。
其中Exception有一个子类称为RuntimeException,这里面右派生出很多常见异常类
NullPointExcepion , IndexOutBoundException等
java语言派生于Error类或者RuntimeException 类的所有异常称为非受查异常,所有的其他异常称为受查异常。
RuntimeException叫做运行时异常,编译时不报错,运行时报错:数组越界ArrayIndexOfBoundsException,空指针NullPointerExcepion,类型转换异常ClassCastException
| 受查异常的两种显示处理方式 |
| thorws关键字用在方法声明中,明确告知调用者不处理这个异常,和这个异常的类型 |
| thorw关键字用在方法的内部,表示人为的抛出异常对象 |
如果一段代码可能抛出受查异常,那么必须显式进行处理。
未处理的异常:文件未找到异常!
java中一切接对象,我们要打开一个File文件,路径假如是d/test.test,但是系统找不到这个文件,就会报错。这时我们用try catch 方法处理
我也不想处理就向上抛出, 在方法的上面加上throws FileNotFoundException
| 自定义异常类 |
Java中虽然已经内置了丰富的异常类,但是我们实际场景中可能还有一些情况需要对异常类进行拓展,创建符合我们实际情况的异常。JDK想不到的我们需要自定义。
自定义异常非常简单:只要继承两个父类
@如果想要显示处理:继承Exception类
@如果不要显示处理:继承RunTimeExcepion类
例如,我们实现一个用户登录功能。
package string_test;
import java.util.Scanner;
public class MyException {
private static final String user_Name="显平";
private static final String passWord="xianping123";
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入用户名");
String userName=scanner.nextLine();
System.out.println("请输出密码");
String password=scanner.nextLine();
if (!userName.equals(user_Name)){
//抛出一个用户名错误异常
throw new UserNameException("用户名错误");
}
if (!password.equals(passWord)){
//抛出密码错误异常
throw new PassWordException("密码错误异常");
}
}
}
// 让用户名异常继承“(java.lang.Exception)运行时异常”就不需要显式处理
class UserNameException extends RuntimeException{
public UserNameException(String msg){
super(msg);
}
}
class PassWordException extends RuntimeException{
public PassWordException(String msg){
super(msg);
}
}
此时我们在处理密码错误的时候就需要 抛出两种异常,我么可以基于已有的异常进行拓展(继承),创建和我们业务相关的异常类。



