Java的异常这块有几位优秀的博主已经介绍的很详细了,我这里就记录一下我的实现过程和学习过程中遇到的问题。
异常(Exception)
java的异常是用于处理程序中异常或错误的一种机制。
回顾:
IDE一般指集成开发环境。集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具.
JDK: Java Development Kit java开发工具箱
JRE:Java Runtime Environment java执行环境
JVM:Java Virtual Machine Java虚拟机
异常分类:
异常处理办法一:使用try…catch…捕获
java是采取面向对象的方式来处理异常。处理过程是:
- 抛出异常: 在执行一个方法时,如果发生异常,则这个方法生成该异常的一个对象,停止当前执行路径,并把异常对象交给JRE(Java Runtime Environment)。
- 捕获异常: JRE得到该异常后,寻找响应的代码来处理该异常,JRE在方法的调用栈中查找,从生成异常方法开始回溯,直到找到响应的异常处理代码为止。
左边程序的执行顺序:
try =》语句1 =》语句2 =》finally =》语句4 (不执行catch里面的语句3).
右边的程序执行顺序:
try =》语句1 =》语句2(遇到异常)=》(不执行语句3)catch =》语句4 =》finally =》语句5.
package oop.oopdemo.testexception;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* 测试异常语句
*
* @author 发达的范
* @date 2020/10/28
*/
public class testException {
public static void main(String[] args) {
FileReader fileReader = null;
//Checked Exception是可以预测的,所以要捕获异常进行处理
try {
fileReader = new FileReader("E:\\hello.txt");
//Reads a single character,其中read()方法:public int read() throws java.io.IOException
char c = (char) fileReader.read();
char c1 = (char) fileReader.read();//Reads a single character.
System.out.println("" + c + c1);//转成字符串进行输出
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
//应该把父类的catch语句放在子类后面
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
try {} catch{} 语句可以使用快捷键生成,Ctrl+Alt+T,或者点击Codes -> Surround With… -> 选择相应的操作即可
try ,catch,finally的执行顺序:
- 执行try…catch…,给返回值赋值
- 执行finally
- 执行return
package oop.oopdemo.testexception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 测试异常捕获语句的执行顺序
*
* @Author 发达的范
* @Date 2020/10/28
* @Time 14:09
*/
public class TestExecutiveOrder {
public static void main(String[] args) {
String string = new TestExecutiveOrder().openFile();
System.out.println(string);
}
String openFile() {
try {
System.out.println("aaa");
FileInputStream fis = new FileInputStream("E:\\(A)PostgraduateFlies\\Javalearing\\abc.txt");
int a = fis.read();
System.out.println("bbb");
return "step1";
} catch (FileNotFoundException e) {
System.out.println("catching!");
e.printStackTrace();
return "step2";
} catch (IOException e) {
e.printStackTrace();
return "step3";
}finally {
System.out.println("finally!");
}
}
}
运行结果:
从执行结果来看:在没有异常时,首先执行try,然后执行 finally,最后执行try中的return语句。
如果try中的文件操作代码发生异常,则执行结果为:
可见,首先进入try按顺序执行,发生异常后,异常语句后面的语句不再执行,直接执行这个异常的捕获语句catch语句,然后再执行finally语句,最后执行return语句。且无论有没有异常出现,都会执行finally语句。
异常处理办法二:声明异常:throws语句
使用throws就是把当前代码的异常自己不处理,抛给调用它的对象进行处理,抛出去几个异常,它的上层就要处理几个异常。
package oop.oopdemo.testexception;
/**
* 测试异常的抛出问题
*
* @author 发达的范
* @date 2020/10/28
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestThrows {
public static void main(String[] args) {
try {
String string = new TestThrows().openFile();
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
}
//自己不处理异常,抛出去,谁调用谁处理,抛给上层
String openFile() throws FileNotFoundException, IOException {
System.out.println("aaa");
FileInputStream fis = new FileInputStream("E:\\(A)PostgraduateFlies\\Javalearing\\abc.txt");
char c = (char) fis.read();
System.out.println("bbb");
return "step1";
}
}
注:main方法里面仍可以继续向上抛throws,但是不推荐。
方法重写中声明异常的原则
- 子类声明的异常范围不能超过父类声明的范围。
- 父类没有声明的异常,子类也不能声明
- 不可抛出原有方法抛出异常可的父类或上层类
- 子类抛出的异常类型数目不可比原有方法抛出的还多(不是指个数)
package oop.oopdemo.testexception;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
/**
* 测试继承之后异常的抛出问题
*
* @author 发达的范
* @date 2020/10/28
*/
class TestExtendsException {
public void method()throws IOException {
}
}
class B extends TestExtendsException {
public void method() throws FileNotFoundException {
}
}
class C extends TestExtendsException {
public void method() {
}
}
class D extends TestExtendsException {
public void method() throws Exception {
}//超出父类异常的范围
}
class E extends TestExtendsException {
public void method() throws IOException, FileNotFoundException {
}
}
class F extends TestExtendsException {
public void method() throws IOException, ArithmeticException {
//父类结合RuntimeException可以
}
}
class G extends TestExtendsException {
public void method() throws IOException, ParseException {
}//父类结合非RuntimeException不可以,超范围
}
至于“ 父类结合RuntimeException可以,父类结合非RuntimeException不可以,超范围”这个问题我还是没搞明白
JDK1.8API中显示:
由此可见,ArithmeticException类和ParseException类都不是IOException类的子类,它们的区别就是:ParseException类与IOException类是平级的,而ArithmeticException类比它们低了一级,我现在对这个疑问的猜想是:子类方法同时throws IOException, ParseException导致抛出的异常类型比父类方法抛出的类型多了。这个问题先留着,待以后解决!
异常处理办法三:手动抛出异常,throw语句(不是throws)
- Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要手工创建并抛出。
- 在捕获一个异常前,必须有一段代码先生成异常对象并把它抛出。这个过程我们可以手工做,也可以由JRE来实现,但是他们调用的都是throw子句。
- 对于一个已经存在的异常类,抛出该类异常对象过程如下:
- 找到一个合适的异常类;
- 创建一个该类的对象;
- 将对象抛出。
package oop.oopdemo.testexception;
import java.io.File;
import java.io.FileNotFoundException;
/**
* 测试手动抛出异常
*
* @Author 发达的范
* @Date 2020/10/28
*/
public class TestThrow {
public static void main(String[] args) {
File f = new File("c:/tt. txt");
if (!f.exists()) {
try {
throw new FileNotFoundException("File can't be found!");//手动 new 一个异常类的对象
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
自定义异常
package oop.oopdemo.testexception;
/**
* 测试使用自定义异常
*
* @Author 发达的范
* @Date 2020/10/28
*/
public class MyException extends Exception {
public MyException() {
}
public MyException(String message) {
super(message);
}
}
class TestMyException {
void test() throws MyException {
}
public static void main(String[] args) {
try {
new TestMyException().test();
} catch (MyException e) {
e.printStackTrace();
}
}
}
使用异常机制的建议:
- 要避免使用异常处理代替错误处理,这样会降低程序的清晰性,并且效率低下。
- 比如:登录界面的密码校验,不需要进行一系列的异常校验(密码位数不对,账号类型错误等),这样反而把问题变复杂了,直接使用if…else…语句就可以解决
- 处理异常不可以代替简单测试-—-只在异常情况下使用异常机制
- 不要进行小粒度的异常处理-—-应该将整个任务包装在一个Try语句块中
- 异常往往在高层处理。