Java10(异常处理)

0.复习面向对象

Java10(异常处理)_第1张图片

1.异常的体系结构

异常:在Java语言中,将程序执行中发生的不正常情况.(开发中的语法错误和逻辑错误不是异常)
异常事件分两类(它们上一级为java.lang.Throwable):
Java10(异常处理)_第2张图片

Error

Java虚拟机无法解决的严重问题。可以不使用针对性的代码进行处理。(如:JVM系统内部错误,资源耗尽等)

Exception

其他因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。(如:空指针访问,网络中断等)
可分为:
编译时异常:在编译期间出现的异常(执行javac.exe命令时,出现异常)
运行时异常:在运行时出现的异常(执行java,exe命令时,出现的异常)
例:

当执行一个程序时,如果出现异常,那么异常之后的代码就不再执行。

2.处理Exception的异常

Java提供的是异常处理的抓抛模型
Java10(异常处理)_第3张图片

“抛”

当我们执行代码时,一旦出现异常,就会在异常的代码处生成一个对应的异常类型的对象,并将此对象抛出。(一旦对象抛出,程序停止执行;异常类的对象抛给方法的调用者)
可分为:
自动抛出

手动抛出(throw + 异常类的对象)

即可以是现成的异常类,也可以自定义的异常类
例:

public class Test4{
	public static void main(String[] args) {                                     
	Circle c = new Circle(2.2);
	Circle c1 = new Circle(2.2);
	System.out.println(c.compareTo(c1));
	System.out.println(c.compareTo(new String("AA")));
	}
}
class Circle {
	private double radius;
	//构造器
	public Circle(double radius){
		super();
		this.radius = radius;
	}
	//方法
	public void setRadius(double radius){
		this.radius = radius;
	}
	public double getRadius(){
		return this.radius;
	}
	public int compareTo(Object obj){
		if(obj == this)
			return 0;
		else if(obj instanceof Circle){
			Circle c1 = (Circle)obj;
			if(this.radius > c1.radius){
				return 1;
			}else if(this.radius == c1.radius){
				return 0;
			}else{
				return -1;
			}
		}else{//手动抛出异常
			throw new RuntimeException("传入的类型有误");
			//抛出自定义的异常(具体编写见下代码块)
			//throw new TestException("传入的类型有误");
			
		}
	}
}

自定义异常类

  1. 自定义的异常类继承现有的异常类
  2. 提供序列号,提供几个重载的构造器

例:

//自定义的异常类
 public class TestException extends RuntimeException{                  
	static final long serialVersionUID = -7123453234353423L;
	public TestException(){

	}
	public TestException(String msg){
		super(msg);
	}	
}

“抓”

抓住上一步抛出的异常类的对象。(抓的方式即为异常处理的方式)
Java提供两种方式来处理一个异常类的对象

方式一(try-catch-finally
try{               
	//可能出现异常的代码
}catch(Exception e1){
	//处理方式1
}catch(Exception e2){
	//处理方式2
}....{
	//处理方式
}finally{
	//一定要执行的代码
}

注:

  • try内声明的变量,类似于局部变量,出了try{}语句,就不能被调用

  • finally是可选的

  • catch语句内部是对异常对象的处理

    • getMessage():显示执行过程中出现的异常
    • printStackTrace():显示堆出现的异常(打印异常信息在程序中出错的位置及原因)
  • 可以有多个catch语句的代码,try中抛出的异常类对象从上往下匹配catch中的异常类1的类型,一旦满足就执行catch中的代码,执行完,就跳过之后的catch语句(多条catch语句满足其一就行

  • 如果异常处理了,那么其后的代码继续执行

  • 若多个catch语句中的异常类型为"包含"关系,需要子类放在父类之前进行处理,否则报错

  • 若多个catch语句中的异常类型为"并列"关系,则无先后放置的要求

  • 不管try,catch中是否处理完异常,及是否有return语句,finally中存放的语句一定执行。

  • try-catch语句可以嵌套

  • 运行时异常,可以不显式处理;编译时异常,必须显式处理

例:常见的异常

import org.junit.Test;
import java.io.*;
import java.util.Date;
public class Test2{
	//1.数组下标越界的异常:ArrayIndexOutOfBoundsException
	@Test
	public void test(){
		try{                                   
		int[] i = new int[10];
		System.out.println(i[10]);
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println("数组下标越界");
		}
	}
	//2.算术异常:ArithmeticException
	@Test
	public void test1(){
		int i = 10;
		try{
		System.out.println(i/0);
		}catch(ArithmeticException e){
			System.out.println("\u7B97\u672F\u5F02\u5E38啦!");
		}
	}
	//3.类型转换异常:ClassCastException
	@Test
	public void test2(){
		try{
		Object obj = new Date();
		String str = (String)obj;
		}catch(ClassCastException e){
			System.out.println(e.getMessage());

		}
	}
	//4.空指针异常:NullPointerException
	@Test
	public void test3(){
		try{
		Person p = null;
		System.out.println(p.toString());
		}catch(NullPointerException e){
			System.out.println(e.fillInStackTrace());
		}
	}
	//编译时异常
	@Test
	public void test4(){
		FileInputStream f = null;
		try{
		f = new FileInputStream(new File("hello.txt"));
		int b;
		while((b = f.read()) != -1){
			System.out.println((char)b);
		}
	}catch(FileNotFoundException e){
		System.out.println("文件不存在");
	}catch(IOException e){
		System.out.println("输入输出有误");
	}finally{
		try{
		f.close();
		}catch(Exception e){
			System.out.println("文件关闭异常");
		}finally{
			System.out.println("程序执行完毕");
		}
	}
	}
}
方式二(throws + 异常的类型)
  • 在方法的声明处,显式的抛出该异常对象的类型
  • 格式:如:
 public static void test6() throwsFileNotFoundException,IOException{ }             
  • 当在此方法内部出现异常时,会抛出异常对象给调用者。
  • 异常的对象可以逐层向上抛,直至main中,在此过程中可以用try-catch-finally进行处理

例:

import java.io.*;

public class Test3{
	public static void main(String[] args) throws FileNotFoundException,IOException{    
		try{
		test6();
		}catch(FileNotFoundException e){
			System.out.println(e.getMessage());
		}catch(IOException e){
			e.printStackTrace();
		}
		
	}
	public static void test6() throws FileNotFoundException,IOException{
		test5();
	}
public static void test5() throws FileNotFoundException,IOException{
		FileInputStream f = new FileInputStream(new File("hello1.txt"));
		int b;
		while((b = f.read()) != -1){
			System.out.println((char)b);
		}
		f.close();
	}
}
  • 子类重写的父类异常方法,其抛出异常类只能是被重写的方法的异常类的子类或异常类型

例:

import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;

public class Test6{
	public static void main(String[] args) throws IOException {   
		A a = new B();
		a.test1();
	}
	
	}
class A{
	public void test1() throws IOException{

	}
}
class B extends A{
	public void test1() throws FileAlreadyExistsException{

	}
}

练习
题一
Java10(异常处理)_第4张图片
结果:
进入A
A-finally
制造异常
进入B
B-finally

题二
Java10(异常处理)_第5张图片

public class EcmDef{
	public static void main(String[] args) {  
		try{
		int i = Integer.parseInt(args[0]);//被除数
		int j = Integer.parseInt(args[1]);//除数
		ecm(i, j);
		}catch(NumberFormatException e){
			System.out.println("输入数据类型不一致");

		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println("缺少命令行参数");
		}catch(ArithmeticException e){
			System.out.println("错误:分母为零");
		}catch(EcDef e){
			System.out.println(e.getMessage());
		}
	}
	public static void ecm(int i,int j) throws EcDef{
		if(i < 0 || j < 0){
			throw new EcDef("输入的数值存在负数");
		}
		System.out.println(i/j);
	}
}
//自定义异常类
class EcDef extends Exception{
	static final long serialVersionUID = -7223453234353423L;
	public EcDef(){

	}
	public EcDef(String msg){
		super(msg);
	}

}

感谢大家的支持,关注,评论,点赞!
参考资料:
尚硅谷宋红康20天搞定Java基础中部

你可能感兴趣的:(Java,开发语言,java)