一、异常处理体系结构
java.lang.Throwable
|------java.lang.Error:一般不编写针对性的代码处理
|------java.lang.Exception:可以进行处理
|-------编译时异常(checked)
|-----IOException
|-----FileNotFoundException
|------ClassNotFoundException
|-------运行时异常(unchecked)
|-------NullPointerException(空指针异常)
|-------ArrayIndexOutOfBoundsException(数组角标越界)
|-------ClassCastException(类型转换异常)
|-------NumberFormatException
|-------InputMismatchException
|-------ArithmeticException
*/
public class ExceptionTest {
//NullPointerException(空指针异常)
@Test
public void test1(){
// int [] arr = null;
// System.out.println(arr[3]);//NullPointerException(空指针异常)
String str = "abc";
str = null;
System.out.println(str.charAt(0));//NullPointerException(空指针异常)
}
//ArrayIndexOutOfBoundsException(数组角标越界)
@Test
public void test2(){
int [] arr = new int[3];
System.out.println(arr[3]);//ArrayIndexOutOfBoundsException(数组角标越界)
}
//ClassCastException(类型转换异常)
@Test
public void test3(){
Object obj = new Date();
String str = (String)obj; //ClassCastException(类型转换异常)
}
//NumberFormatException转换异常
@Test
public void test4(){
String str = "123";
str = "abc";
int num = Integer.parseInt(str);
}
//InputMismatchException输入不匹配异常
@Test
public void test5(){
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();//InputMismatchException输入不匹配异常
System.out.println(score);
}
//ArithmeticException算术异常
@Test
public void test6(){
int a = 10;
int b = 0;
System.out.println(a/b);////ArithmeticException算术异常
}
}
异常处理机制一
异常处理:抓抛模型
过程一,抛:程序执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常
对象,并将此对象抛出,一旦抛出对象后,其后代码不在执行
过程二,抓:可以理解异常处理的方式一、try-catch-finally 二、 throws
try-catch-finally 的使用
try{
可能出现问的代码
}catch(异常类型1 变量名1){
处理机制
}catch(异常类型2 变量名2){
处理机制
} catch(异常类型3 变量名){
处理机制
}...
finally{
一定执行的代码
}
说明
1.finally是可选的
2.使用try将可能出现异常的代码包装起来,执行过程中,一旦出现异常
,就会生成一个对异常的对象,根据此对象的类型去catch匹配
3.一旦try中异常对象匹配到某个catch时,就进入catch中进行异常的处理。一旦处理
完成后,就跳出try-catch结构(没有finally的情况)
4. catch 中异常类型没有子父类关系,则谁声明在上,谁声明在下没有关系
如果存在子父类关系。则父类必须声明在最后,否则报错
5.常用的异常方法string e.getMessage()和printStackTrace()打印堆栈信息
6.在try结构定义的变量,再出了try结构不能在被调用
使用try-catch finally 处理编译时异常使得程序在编译时不在报错,运行时
还可能报错;相当于使用try catch finally 将一个编译时可能出现的异常
延迟到了运行时
开发中由于运行时异常比较常见,通常不针对运行时异常编写try--catch-finally了
针对编译时异常一定考虑异常处理
实例1
public class ErrorTest1 {
@Test
public void test1(){
String str = "123";
str = "abc";
try {
int num = Integer.parseInt(str);
System.out.println("1");//不执行
}catch (NullPointerException e){
System.out.println("空指针出现异常");
System.out.println("2");
}catch (NumberFormatException e){
System.out.println("出现数值转换异常");
System.out.println(e.getMessage());//打印报错
e.printStackTrace();//打印堆栈报错信息
}catch (Exception e){
System.out.println("异常");
}
System.out.println("3");
}
}
测试结果
java.lang.NumberFormatException: For input string: "abc" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at com.chenxi.java.ErrorTest1.test1(ErrorTest1.java:45) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 出现数值转换异常 at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) For input string: "abc" at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 3 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Process finished with exit code 0
结构finally使用
try -- catch ---finally
1.finally 是可选的
2.finally 声明的语句是一定会被执行的;即使catch 中又出现异常,
try 中有return语句,catch 中也有return语句等情况
数据库链接、输入输出流、网络编程Socket等资源,JVM 是不会自动回收的,需要
手动进行资源释放,此时的资源释放,就需要声明在finally中
示例
public class FinallyTest {
@Test
//finally释放资源操作
public void test2() {
FileInputStream fis = null;
try {
File file = new File("hello.txt");
fis = new FileInputStream(file);
int data= fis.read();
while (data != -1){
System.out.println((char)data);
data = fis.read();
}
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if (fis !=null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void tsetmeth(){
FinallyTest f1 = new FinallyTest();
int i = f1.method();
System.out.println(i);
}
public int method(){
try {
int[] arr = new int[10];
System.out.println(arr[10]);
return 1;
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();
return 2;
}finally {
System.out.println("我一定会执行");
}
}
@Test
public void text1(){
try {
int a = 10;
int b = 0;
System.out.println(a/b);
}catch (ArithmeticException e){
// e.printStackTrace();
int[] arr = new int [10];
System.out.println(arr[10]);
}catch (Exception e){
e.printStackTrace();
} finally {
System.out.println("百年孤独!");
}
}
}
开发中如何选择使用try---catch---finally 还是使用throws
*如果父类中被重写的方法没有throws方式处理掉,则子类重写的方法也不能使用
* throws ,意味着如果子类重写的方法有异常,必须使用try-catch-finally方式处理
* 执行的方法A中,先后调用了另外几个方法,这几个方法是递进执行的关系,建议这几个方法使用throw的方式
* 进行处理。而执行的方法a可以考虑使用try-catch-finally 的方式进行处理
*
示例
方法重写的规则之一
子类重写的方法抛出异常类不大于父类被重写的方法抛出的异常类型
*/
public class OverrideTest {
public static void main(String[] args) {
OverrideTest test = new OverrideTest();
test.display(new SubClass());
}
public 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 FileNotFoundException {
}
}
关于异常对象的产生1.系统自动生成异常对象
2. 手动生成异常,并抛出异常
手动抛出异常示例
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
s1.regist(-1001);
System.out.println(s1);
}
}
class Student{
private int id;
public void regist(int id){
if (id >0){
this.id= id;
}else {
// 手动抛异常
throw new RuntimeException("非法数字");
}
}
}
测试结果
Exception in thread "main" java.lang.RuntimeException: 非法数字
at com.chenxi.java3.Student.regist(StudentTest.java:18)
at com.chenxi.java3.StudentTest.main(StudentTest.java:6)
自定义异常类
自定义异常类
1.继承现有的异常结构:RuntimeException、Exception
2.提供全局常量:serialVersionUID
3.提供重载构造器
示例
定义异常类
public class MyException extends Exception {
static final long serialVersionUID = -7034897190745766938L;
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
测试异常处理
public class StudentTest {
public static void main(String[] args) {
try {
Student s1 = new Student();
s1.regist(-1001);
System.out.println(s1);
} catch (Exception e){
System.out.println(e.getMessage());
}
}
}
class Student{
private int id;
public void regist(int id) throws MyException {
if (id >0){
this.id= id;
}else {
// 手动抛异常
throw new MyException("不能输入负数");
}
}
}
测试结果
不能输入负数
原文:https://www.cnblogs.com/rdchenxi/p/14645248.html