重要的问题
1、try-catch-finally和throws的区别
try-catch-finally:是真正将异常处理了
throws:只是将异常抛给了方法的调用者,并没有真正将异常处理掉
2、throws和throw的区别
throws是异常处理的一种方式,声明在方法的声明处。
throw表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体中。
1、异常概述
开发过程中的语法错误和逻辑错误不是异常
1、异常是程序执行过程中发生的不正常状况
分为两类:Error和Exception
Error:Java虚拟机无法解决的严重问题,不能用针对性代码处理,只能改代码
Exception:其他因编程错误或偶然外在因素导致的一般性问题,可以使用针对性的代码进行处理。
2、异常分类(可对异常进行处理)
1、编译时异常(可控式异常)
IOException 当发生某种I/O异常时,抛出此异常
ClassNotFoundException 类没有找到异常
SQLException 提供关于数据库访问错误或其他错误信息的异常
NoSuchFieldException 类不包含指定名称的字段时产生的信号
NoSuchMethodException 无法找到某个特定方法时,抛出该异常
2、运行时异常
IndexOutOfBoundsException 数组索引值越界异常(集合或数组的索引值超出范围时抛出该异常)
NullPointerException 空指针异常
ClassCastException 当试图将对象强制转换为不是实例的子类时抛出异常
NumberFormatException 数字格式异常
InputMismatchException 控制台输入的数据类型与设置的不匹配
ArithmeticException 算数异常
补:
开发中由于运行时异常比较常见,我们通常不针对运行时异常编写try-catch-finally了。针对编译时异常,一定要考虑异常的处理。
3、获取异常信息
在Java中Throwable类时所有异常类的超类。
有四种获取异常信息的方法
e.printStackTrace();
e.getMessage();
e.getLocalizedMessage();
e.toString();
public class ExceptionMessage {
public void printExceptionInfo() { // 定义成员方法
try {
int x = 100; // 定义局部变量x
int y = 0; // 定义局部变量y
int z = x / y; // 计算x除以y的商
// 输出计算结果
System.out.println(x + "除以" + y + "的商是:" + z);
} catch (Exception e) {
e.printStackTrace(); // 输出异常到标准错误流
// 使用getMessage方法输出异常信息
System.out.println("getMessage方法: " + e.getMessage());
// 使用getLocalizedMessage方法输出异常信息
System.out.println("getLocalizedMessage方法: " + e.getLocalizedMessage());
// 使用toString方法输出异常信息
System.out.println("toString方法: " + e.toString());
}
}
public static void main(String[] args) {
ExceptionMessage e = new ExceptionMessage(); // 创建类的实例
e.printExceptionInfo(); // 调用方法
}
}
运行结果
4、处理异常
Java处理异常的模式
1、try-catch-finally
2、throws-异常类型
常用的异常对象处理的方式:e.getMessage() 和e.printStackTtrace()
①“抛”,程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出。一旦抛出对象以后,其后的代码就不再执行。
②“抓”,异常处理的方式
1、使用try-catch处理异常
对代码进行异常检测,并对检测的异常传递给catch处理。对异常进行捕获处理。
格式
try {
需要正常执行的语句
} catch(Exception ex) {
对异常进行处理的语句
}
2、使用try-catch-finally处理异常
格式
try {
需要执行的语句
} catch(Exception ex) {
对异常进行处理的语句
} finally {
一定会被处理的语句
}
还有多个catch的情况
try {
//可能出现异常的代码
} catch(异常类型1 变量名1) {
//处理异常的方式1
} catch(异常类型2 变量名2) {
//处理异常的方式2
} catch(异常类型3 变量名3) {
//处理异常的方式3
} finally {
一定会执行的代码
}
补:
①catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
②如果有子父类关系,则子类一定声明在父类的上面。否则会报错。
③在try结构中声明的变量,在出了try结构后,就不能再被调用
④finally是可选的
⑤try-catch-finally结构可以嵌套
⑥手动的进行资源的释放,需要声明在finally中
3、使用try-finally处理异常
对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认jvm抛出。异常是没有捕获处理的。但是功能所开启资源需要进行关闭,所有finally。只为关闭资源。
格式
try {
需要执行的语句
} finally {
一定被处理的语句
}
例子:
public class RuntimeExceptionTest {
public static void method() {
try {
System.out.println("进入方法"); //第1执行
throw new RuntimeException("制造异常"); //最后执行
} finally {
System.out.println("使用方法的finally"); //第2执行,等等再 执行
}
}
}
public class test {
public static void main(String[] args) {
RuntimeExceptionTest a = new RuntimeExceptionTest();
try {
a.method();
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
运行结果
5、抛出异常
throws关键字可以在定义方法时抛出异常,throw是在方法中抛出异常。
1、使用throws声明抛出异常(是异常处理的第二种方式)
“throws+异常类型”写在方法的声明处
,指明此方法执行时可能会抛出的异常类型。异常代码后续的代码就不再执行。
格式
数据类型 方法名(形参列表) throws 异常类1,异常类2,.....,异常类n {
方法体;
}
public void method() throws IOException {
}
例如
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest {
public void method() throws FileNotFoundException,IOException { //声明在方法中
File file = new File("hello.txt");
FileInputStream fis=new FileInputStream(file);
int d=fis.read();
while(d!=-1) {
System.out.println((char)d);
d=fis.read();
}
fis.close();
System.out.println("不能再执行了!"); //出现异常后这个语句就不再执行了
}
}
import java.io.IOException;
public class Test {
public static void main(String[] args) {
ExceptionTest a = new ExceptionTest();
try {
a.method();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
补:开发中如何选择使用try-catch–finally还是使用throws?
①如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,即子类重写的方法中有异常,必须使用try-catch-finally方式处理。父类没有抛异常,子类就不能抛异常。
②在执行的方法a中,先后调用了另外几个方法,这几个方法是递进关系,建议使用throws方式处理,而执行的方法a可以使用try-catch-finally方式处理
2、使用throw语句抛出异常(手动抛出异常对象)
用来抛出一个指定的异常对象
格式
throw new Exception("对异常的说明");
通常使用Exception
或RuntimeException
,是自定义的异常类
public class Student {
private int id;
public void get(int id) throws Exception {
if(id>0) {
this.id=id;
} else {
//System.out.println("您输入的数据非法!"); 以前是这样处理的
throw new Exception("您输入的数据非法!");
}
}
}
public class StudentTest {
public static void main(String[] args) {
try {
Student s = new Student();
s.get(-100);
System.out.println(s);
} catch (Exception e) {
//e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
运行结果
6、自定义异常
如何自定义异常类:(步骤)
1、继承于现有的异常结构:Exception、RuntimeException
2、提供全局变量:serialVersionUID
3、提供重载的构造器
1、创建自定义异常类
继承于现有的异常结构:Exception、RuntimeException
提供重载的构造器,形参是异常的描述信息
public class MyException extends Exception {
/*
为什么要定义构造函数,因为看到Java中的异常描述类中有提供对异常对象的初始化方法。
*/
public MyException() {
super();
}
public MyException(String message) {
super(message);// 如果自定义异常需要异常信息,可以通过调用父类的带有字符串参数的构造函数即可。
}
}
2、使用自定义异常类
通过throw语句抛出异常
MyException类
public class MyException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public MyException() {
}
public MyException(String s) {
super(s);
}
}
Student类
public class Student {
private int id;
public void get(int id) throws Exception {
if(id>0) {
this.id=id;
} else {
throw new MyException("不能输入负数!");
}
}
}
Test类
public class Test {
public static void main(String[] args) throws Exception {
Student s=new Student();
try {
s.get(-100);
System.out.println(s);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
运行结果
7、异常的使用原则
①不要过多地使用异常,这样会增加系统的负担
②在方法中使用try-catch捕获异常时,要对异常做出处理
③try-catch语句块的范围不要太大,否则不利于对异常的分析
④一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或子异常