Java基础(异常)
标签(空格分隔): Java
Java程序在执行过程中所发生的异常事件可分为两类:
Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源
耗尽等严重情况。比如:StackOverflowError和OOM。一般不编写针对性 的代码进行处理。 Exception:
其它因编程错误或偶然的外在因素导致的一般性问题,可以使 用针对性的代码进行处理。例如: 空指针访问 试图读取不存在的文件 网络连接中断
数组角标越界
一、异常体系结构
java.lang.Throwable
- Java.lang.Error:一般不编写针对性的代码进行处理
- java.lang.Exception:可以进行异常处理
|——编译时错误(checked)
——|——IOException
————|——FileNotFoundException
——|——ClassNotFoundException
|——运行时异常(unchecked)
——|——NullPointerException//空指针异常
——|——ArrayIndexOutOfBoundsException//数组教区
——|——ClassCastException//类型转换异常
——|——NumberFormatException//
——|——InputMismatchExceptionn//输入不匹配
——|——ArithmeticExceptionn//算数异常
运行时异常的举例:
import java.util.Date;
import java.util.Scanner;
public class ExceptionTest {
// NullPointerException
public void test1(){
int[] arr = null;
System.out.println(arr[2]);
}
public void test2(){
// ArrayIndexOutOfBoundsException
int[] arr = new int[3];
System.out.println(arr[3]);
// StringIndexOutOfBoundsException
String str = "abc";
System.out.println(str.charAt(3));
}
public void test3(){
// ClassCastException
Object obj = new Date();
String str = (String) obj;
}
public void test4(){
// NumberFormatException
String str = "123";
str = "abc";
int num = Integer.parseInt(str);
}
public void test5(){
// InputMismatchExceptionn
Scanner scanner = new Scanner(System.in);//输入函数
int score = scanner.nextInt();
System.out.println(score);
}
public void test6(){
int a = 10;
int b = 0;
System.out.println(a / b);
}
}
异常的处理:抓抛模型
一、
过程一:“抛”:程序在正常处理中,一旦出现异常,就会在异常代码出生成一个对应异常类的对象。并将此对象抛出。一旦抛出对象之后,其后的代码就不再执行。
关于异常对象的产生:
①系统自动生成的异常对象
②手动的生成一个异常对象,并抛出
public class StudentTest {
public static void main(String[] args) {
try{
Student s = new Student();
s.regist(-1001);
System.out.println(s);
} catch (Exception e){
System.out.println(e.getMessage());
}
}
}
class Student{
private int id;
public void regist(int id) throws Exception{
if(id > 0){
this.id = id;
}else {
// System.out.println("您输入的数据非法!");
//手动的抛出异常对象
// throw new RuntimeException("您输入的数据非法!");
throw new Exception("您输入的数据非法!");//上面改为public void regist(int id) throws Exception{
}
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
过程二:“抓”:可以理解异常的处理方式:
①try-catch-finally
②throws
二、try-catch-finally的使用
异常处理方式一:try-catch-finally
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//异常处理的方式1
}catch(异常类型2 变量名2){
//异常处理的方式2
}catch(异常类型3 变量名3){
//异常处理的方式3
}
...
finally{
//一定会执行的代码
}
说明:
- finally是可选的,final是一定会被执行的代码。即使catch中又出现了异常,try中有return语句,catch中有return语句等情况。像数据库连接、输入输出流、网络编程Socket等资源,jvm是不能自动回收的,需要我们手动的进行资源的释放。此时的资源释放,就需要声明在finally中。
- 使用try将可能出现异常的代码包装起来,执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,娶catch中进行匹配
- 一旦try中的异常对象匹配到某一个catch时,就进入catch进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(在没有写finally的情况下),继续执行其后的代码。
- catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类上面。否则,报错。 - 常用的异常对象处理的方式:①String getMessage() ②printStackTrace()
- 在try结构中声明的变量,再出了try结构以后,就不能再被调用
体会1:使用try-catch-finally处理编译时异常,是得程序在编译时不再报错,但运行时仍可能报错。相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
体会2:开发中,由于运行时异常比较常见,所以我们通常不针对运行异常编写try-catch-finally了。针对于编译时异常,我们说一定要考虑异常的处理。
public class ExceptionTest1 {
public void test1(){
String str = "123";
str = "abc";
int num = 0;
try {
num = Integer.parseInt(str);
}catch (NullPointerException e){
System.out.println("出现数值转换一场,不要着急...");
}
num = 2;
}
}
加final的
public class ExceptionTest1 {
public void test1(){
try {
int a = 10;
int b = 0;
System.out.println(a / b);
}catch (ArithmeticException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("final是一定会被执行的,也是可选的");
}
}
}
异常处理方式二:throws + 异常类型
-
“throws + 异常类型”写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象。此对象满足throws后异常类型时,就会被抛出。异常代码后面的代码,就不再执行! -
体会:try-catch-finally:真正的将一场给处理掉了。throws的方法只是将异常抛给了方法的调用者。并没有真正地将异常处理掉。
-
开发中如何使用try-catch-finally 还是使用throws?
3.1 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理。
3.2 执行的方法a中,先后又调用了另外几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws的方式进行处理,而执行的方法a可以考虑使用try-catch-finally方式进行处理。public void test1() throws IOException { }
方法重写的规则
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型。
import java.io.IOException;
public class ExceptionTest1 {
public static void main(String[] args) {
ExceptionTest test = new ExceptionTest();
test.display(new SubClass());
}
public static void display(SuperClass s){
try {
s.method();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SuperClass{
public void method() throws IOException{
}
}
class SubClass extends SuperClass{
@Override
public void method() throws IOException {
}
}
如何自定义异常类
-
继承与现有的异常结构:RuntimeException 、 Exception
-
提供全局常量:serialVersionUID
-
提供重载的构造器
public class StudentTest { public static void main(String[] args) { try{ Student s = new Student(); s.regist(-1001); System.out.println(s); } catch (Exception e){ System.out.println(e.getMessage()); } } } class Student{ private int id; public void regist(int id) throws MyException /*throws Exception*/{ if(id > 0){ this.id = id; }else { // System.out.println("您输入的数据非法!"); //手动的抛出异常对象 // throw new RuntimeException("您输入的数据非法!"); // throw new Exception("您输入的数据非法!");//上面改为public void regist(int id) throws Exception{ throw new MyException("不能输入负数"); } } @Override public String toString() { return "Student{" + "id=" + id + '}'; } } public class MyException extends Exception{ static final long serialVersionUID = -2324353456634L; public MyException(){ } public MyException(String msg){ super(msg); } }