Java基础:第七章 异常处理

面试题:
1、常见的异常都有哪些?举例说明,怎么处理异常
运行时异常:ArithmeticException 算术异常,ArrayIndexOutOfBoundsException数组角标越界,ClassCastException 类型转换异常
编译时异常(checked):IOException
不针对运行时异常编写try-catch-finally
2、throws、throw区别
throws声明异常是异常处理的方式, 捕获异常,声明在方法的声明处。
throw手动生成异常对象,抛出异常,声明在方法体内。可以同时使用,先抛出后捕获
3、final、finally、finalize三者的区别?
finalize不是关键字,是一个方法对象回收前会自动调用该方法

一、7.1 异常体系结构

Java程序在执行过程中所发生的异常事件可分为两类:
Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源
耗尽等严重情况。比如:StackOverflowError和OOM。一般不编写针对性
的代码进行处理。
Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使
用针对性的代码进行处理。例如:
空指针访问
试图读取不存在的文件
网络连接中断
数组角标越界

java.lang.Throwable 类
|-----java.lang.Error(子类):一般不编写针对性的代码进行处理。
|-----java.lang.Exception:可以进行异常的处理

  •  |------编译时异常(checked)
    
  •  			|-----IOException
     			|-----FileNotFoundException
     			|-----ClassNotFoundException
    

|------运行时异常(unchecked,RuntimeException)

  •  			|-----NullPointerException 空指针异常
    
  •  			|-----ArrayIndexOutOfBoundsException数组角标越界
    
  •  			|-----ClassCastException 类型转换异常
    
  •  			|-----NumberFormatException 数值类型转换失败
    
  •  			|-----InputMismatchException 键入不匹配
    
  •  			|-----ArithmeticException 算术异常:除数分母为0
    
public class ExceptionTest{
//InputMismatchException
	@Test
	public void test5(){
	    Scanner scanner =new Scanner(System.in);
	    int score = sannner.nextInt();
	    System.out.printIn(score);//输入字母会报InputMismatchException异常
	    scanner.close();
	
	}
//NumberFormatException
	@Test
	public void test4(){
	String str ="123";
	int num =Integer.parsInt(str);
	//String str2 ="abc";
	//int num =Integer.parsInt(str2); 字母不能强制转换为数值
	}
//ClassCastException 类型转换异常
    @Test
    public void test3(){
    Object obj =new Date();
    String str =(String)obj;//报错数据类不能转换为string
    }
//NullPointerException
	@Test
	public void test1(){
		
//		int[] arr = null;//数组
//		System.out.println(arr[3]);
		
		//String str = "abc";
		str = null;
		System.out.println(str.charAt(0));//打印首字符
		
	}
}

二、异常处理

抓抛模型
过程一:“抛”:程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。
并将此对象抛出。
一旦抛出对象以后,其后的代码就不再执行。
关于异常对象的产生:
① 系统自动生成的异常对象
② 手动的生成一个异常对象,并抛出(throw)

过程二:“抓”:可以理解为异常的处理方式:
① try-catch-finally ② throws

try-catch-finally的使用

try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}catch(异常类型3 变量名3){
//处理异常的方式3
}

finally{
//一定会执行的代码
}

  • 说明:
  1. finally内容是可选的。
  2. 使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。无异常跳过catch执行finally
  3. 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的
    try-catch结构(在没有写finally的情况)。继续执行其后的代码
  4. catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
    catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错
  5. 常用的异常对象处理的方式: ① String getMessage() ② printStackTrace()
  6. 在try结构中声明的变量,再出了try结构以后,就不能再被调用
  7. try-catch-finally结构可以嵌套

体会1:使用try-catch-finally处理编译时异常,是得程序在编译时不报错,但是运行时仍可能报错。
体会2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。
针对于编译时异常,我们说一定要考虑异常的处理。

public class ExceptionTest1 {
	
	
	@Test
	public void test2(){
		try{
			File file = new File("hello.txt");
			FileInputStream fis = new FileInputStream(file);
			
			int data = fis.read();
			while(data != -1){
				System.out.print((char)data);
				data = fis.read();
			}
			
			fis.close();
		}catch(FileNotFoundException e){
			e.printStackTrace();
		}catch(IOException e){//FileNotFoundException是其子类
			e.printStackTrace();
		}
	}
	
	@Test
	public void test1(){
		
		String str = "123";
		str = "abc";
		int num = 0;
		try{
			num = Integer.parseInt(str);
			
			System.out.println("hello-----1");
		}catch(NumberFormatException e){
//			System.out.println("出现数值转换异常了,不要着急....");
			//String getMessage():
//			System.out.println(e.getMessage());
			//printStackTrace():
			e.printStackTrace();
		}catch(NullPointerException e){
			System.out.println("出现空指针异常了,不要着急....");
		}catch(Exception e){
			System.out.println("出现异常了,不要着急....");
			
		}
		System.out.println(num);
		
		System.out.println("hello-----2");
	}
	
}
public class Finally{


}

try-catch-finally中finally的使用:

  • 1.finally是可选的
  • 2.finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有
  • return语句等情况。
  • 3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中。
    快捷操作:选中try的内容,右键surround with,try/catch block

printStackTrace打印堆栈信息

public void test2(){
		FileInputStream fis = null;//初始化为null
		try {
			File file = new File("hello1.txt");
			fis = new FileInputStream(file);
			
			int data = fis.read();
			while(data != -1){
				System.out.print((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();
			}
		}
	}

throws +异常类型

public class Expection{
     public static void main(String args){
     try{
			method2();
			
		}catch(IOException e){
			e.printStackTrace();
		}
     }
     public static void method2() throws IOException{
     method1();
     }
     public static void method1()throws FileNotFoundException,IOException{
     }
}

开发中如何选择使用try-catch-finally 还是使用throws?

  • 1 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,子类重写的方法中有异常,必须使用try-catch-finally方式处理。
  • 2 执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws 的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。

三、7.5手动抛出异常

public void regist(int id) throws Exception {
if(id > 0){
this.id = id;
}else{
//手动抛出异常对象
throw new RuntimeException(“您输入的数据非法!”);
// throw new Exception(“您输入的数据非法!”);

//throw new String(“不能输入负数”); //错误的,不是异常类型
}
}

如何自定义异常类?

  1. 继承于现有的异常结构:RuntimeException(运行时异常,不用显示处理:下例中 public class MyException extends RuntimeException时改为public void regist(int id) ) 、Exception
  2. 提供全局常量:serialVersionUID
  3. 提供重载的构造器
    4.通用结构
public class MyException extends Exception{
	
	static final long serialVersionUID = -7034897193246939L;//静态变量随类定义,标识MyException
	
	public MyException(){
		
	}
	
	public MyException(String msg){
		super(msg);
	}
}

package com.atguigu.java2;


class Stydent{
    private int id;
     public void regist(int id) throws Exception {//显示处理,throws Myexception也可
		if(id > 0){
			this.id = id;
		}else{
			//手动抛出异常对象
		throw new MyException("不能输入负数");

		}
		
	}

}

练习3 判断输出结果

package com.java;

public class ReturnExceptionDemo {
	static void methodA() {
		try {
			System.out.println("进入方法A");
			throw new RuntimeException("制造异常");//没有输出
		} finally {
			System.out.println("用A方法的finally");
		}
	}

	static void methodB() {
		try {
			System.out.println("进入方法B");
			return;
		} finally {
			System.out.println("调用B方法的finally");
		}
	}

	public static void main(String[] args) {
		try {
			methodA();
		} catch (Exception e) {
			System.out.println(e.getMessage());//输出手动抛出的异常
		}
		
		
		
		methodB();
	}
}

输出
进入方法A
用A方法的finally
制造异常
进入方法B
调用B方法的finally

练习4

接收命令行的两个参数
main方法中 ’int i = Integer.parseInt(args[0]);’
’int j = Integer.parseInt(args[1]);’

public class EcmDef {
	public static void main(String[] args) {
		try{
			int i = Integer.parseInt(args[0]);
			int j = Integer.parseInt(args[1]);
			
			int result = ecm(i,j);
			
			System.out.println(result);
		}catch(NumberFormatException e){
			System.out.println("数据类型不一致");
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println("缺少命令行参数");
		}catch(ArithmeticException e){
			System.out.println("除0");
		}catch(EcDef e){	//自定义异常类
			System.out.println(e.getMessage());
		}
		
	}
	
	public static int ecm(int i,int j) throws EcDef{
		if(i < 0 || j < 0){
			throw new EcDef("分子或分母为负数了!");
		}
		return i / j;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值