异常:程序没按照预计的结果运行,在运行过程中发生了“错误”。
1、异常的基本语法: (捕获异常)
try{
//可能会产生异常的代码,如除0、数组越界、空指针等
}[catch...0..N](可能出现异常的类型 异常对象引用 ){
//出现异常以后如何处理
}[finally]{
//异常的出口,最终会执行的代码块
}
(1)出现异常如果不处理 ,则发生异常之后的代码都将不再执行
(2)使用 try...catch...处理异常
(3) Java中一切都是类,异常也是类,因此catch代码块只能捕获相应的“异常”类型
public static void main(String[] args) {
int[] data =new int[] {1,3,5};
data = null;
System.out.println("before........");
try {
//可能会产生异常的代码
System.out.println(data[1]);
System.out.println("try中的其他代码块");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组越界异常产生了");
}catch(NullPointerException e){
System.out.println("空指针异常产生了");
}
System.out.println("after..........");
}
(4)Exception异常是所有异常类的父类,如果catch代码块中捕获的是Exception这个类型,就可以接收到所有的异常类型。(不推荐)
a. 若此时明确知道 try 中可能产生的异常类型,如数组越界异常、空指针异常等,catch捕获明确的相关类型。
b. 若此时不太明确可能产生哪些异常,就使用Exception共同的父类。所有异常的子类都会向上转型为Exception的引用。
int[] data =new int[] {1,3,5};
// data = null;
System.out.println("before........");
try {
//可能会产生异常的代码
System.out.println(data[5]);
System.out.println("try中的其他代码块");
}catch(Exception e){
System.out.println("异常产生了");
}
System.out.println("after..........");
5、关于错误“堆栈”信息
6、关于 finally 代码块 :无论是否有异常产生,最终都会执行finally代码块中的代码,若finally中存在的返回值,则会覆盖掉try 或者catch中的返回值,因此,finally中一般不设置返回值。
一般来说,资源的释放、方法的关闭操作都在finally代码块中。
7、异常的处理流程
8、throws 和throw关键字 — 人为抛出异常
throws关键字:用在方法声明上,表示该方法可能会产生的异常类型,但是本方法中不处理该异常,若异常产生抛回给调用者。
throw关键字:用在方法内部,表示人为产生异常对象并抛出。异常对象的产生都是发生异常后由JVM产生的,若需要人为产生异常对象,就使用throw关键字。
9、异常体系:JDK内部异常的继承关系
Java中的异常分为两类,一类称之为“受查异常”,另一类称之为“非受查异常”
非受查异常:RuntimeException 以及其子类包括Error及其子类称之为非受查异常,编译阶段可以不显示进行异常处理(try...catch / throws抛出)
RuntimeException(运行时异常,编译阶段不报错,运行时出错。) | ArrayIndexofBoundException-数组越界异常 |
NullPointerException-空指针异常 | |
ClassCastException-类型转换异常 | |
ArithmeticException-算术异常 | |
Error-程序内部错误,一般来说,出现这种错误,程序没法再正常执行下去,只能退出程序 | OutofMemoryError-堆内存溢出错误 |
StackOverflowError-栈溢出错误 |
受查异常:除了这些非受查异常以外的其他异常类属于受查异常,必须在编译阶段现实进行异常的处理,否则编译就会出错。
显示处理方法:
a.使用 try ... catch... 捕获这个异常
b.调用者使用throws 向上抛出异常
10、自定义异常 :
JDK内部已经帮我们提前定义好了很多的异常,但是在某些业务场景下,出现的错误需要我们自定义异常类(用户登录时,用户名不对、密码错误等,这些错误就需要我们来自定义异常类)
自定义异常类只需要继承相关的父类即可:
a.若希望该异常必须显示处理-继承Exception父类。
b.若该异常不需要显示处理-继承RunTimeException父类。
public class DefineExceptionTest {
private static String User_Name = "小羊";
private static String Password = "123456";
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String userName = scanner.nextLine();
if (!User_Name.equals(userName)){
//抛出用户名异常
throw new UserNameException("用户名错误");
}
System.out.println("请输入密码:");
String password = scanner.nextLine();
if (!Password.equals(password)) {
//密码登录异常
throw new UserNameException("密码错误");
}
}
}
class UserNameException extends RuntimeException{
public UserNameException(String message){
//调用父类的有参构造,super关键字必须显示调用
super(message);
}
}
class PasswordException extends RuntimeException{
public PasswordException(String message){
super(message);
}
}