异常解析

为什么需要学习异常?

  • 1.观察程序的错误
  • 2.能够让错误指示程序修改

异常的概述:

异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。简单来说就是程序出现了不正常的情况。
异常本质就是Java当中对可能出现的问题进行描述的一种对象体现
异常的分类:

异常(Exception)的分类

  • 编译时异常:

凡是Exception或者是Exception的子类都成为编译时异常,这种是可以解决的,一般编译不通过

  • 运行时异常:

凡是RuntimeException或者是RuntimeException的子类都成为运行时异常,这种也是可以解决的,一般都是代码不够严谨或者逻辑错误

  • 错误 (Error)

    我们无法解决,这不是我们所关心

异常框架体系结构图

在这里插入图片描述
常见异常分类
在这里插入图片描述

Throwable类讲解

  • 提取保存在堆栈中的错误信息

  • 如何查找错误根源:从下往上依次看,先看你能够看懂的,再看别人写的或者是源码的

为什么需要处理异常?

目的:在程序出现问题后,还能够让程序继续执行

JVM(虚拟机)处理异常的方式:

  • 1.打印错误信息
    a.异常的类名
    b.异常信息
    c.异常的位置
    d.错误的行号
  • 2.将程序停止

异常处理的标准格式:

  •  1.能够显示声明的异常尽量显示声明,提高程序的可读性
    
  •  2.在最后都必须加上 Exception 作为父类异常,防止程序异常停止,提高程序的安全性
    

自己处理异常

try…catch

1.try…catch…finally
2.throws

异常处理的格式:

2.1 try…catch…finally

2.2 try { / / 只 能 有 一 个 t r y \color{red}{//只能有一个try} //try
可能出现问题的代码;
} catch(异常类名 异常对象) { / / / / 注 意 c a t c h . . . 可 以 写 多 个 \color{red}{注意catch{ ... }可以写多个} ////catch...
异常处理的代码
} finally {
释放未关闭的资源
}

异常处理的执行流程

1.程序执行到错误代码的地方,系统会抛出一个异常对象
ArithmeticException ae = new ArithmeticException("/by zero");
throw ae;//抛出ae对象
2.程序转入catch块与声明的exception进行逐个匹配
3.匹配成功,程序执行 catch代码
4.匹配失败,程序还给JVM处理
在这里插入图片描述

注意事项
  • 1.try块代码尽量越少越好
  • 2.一旦try块代码中出现异常,无论try块后面有多少行代码,都不会被执行
  • 3.catch块中异常参数匹配同样满足多态 Exception e = new ArithmeticException("/by zero");
  • 4.try块只能够有一个,catch可以有多个,try可以和finally组合,try可以和catch组合,try可以和catch和finally组合
  • 5.一般会把Exception作为catch的参数类型放在异常处理格式的最后,Execption作为父类异常参数只能够出现在异常的最后面,先子类后父类

案例:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a=10;
		int b=0;
		int arr[]=new int[3];
		Object obj=null;
		Object oj="zhangsan";
		try{
			arr[3]=5;                     //出现异常try后面的代码不会执行
			obj.equals("");
			System.out.println(a/b);
		} catch (ArithmeticException e) {
			System.out.println("出问题了,除数不能为0");
		} catch (ArrayIndexOutOfBoundsException aioobe) {
			System.out.println("数组索引越界");
		} catch (NullPointerException ne) {
			System.out.println("空指针异常");
		} catch (Exception e) {                   //Exception  放在最后
			System.out.println("出问题了");
		}
	}
	//只打印//数组索引越界
	//解析:出现异常try后面的代码不会执行

throws处理异常(声明异常)

声明异常在下面代码2
为什么有try…catch方式还需要学习throws处理异常?
在开发中,有的时候我们没有权限处理该异常,我们不知道该如何处理异常,我不想处理异常,所以我们可以将异常抛出,抛出给调用者处理

throws处理异常的格式:
	  	[访问权限修饰符] 返回值类型 方法名(参数列表) [throws 异常类名]{
	  		方法体;
	 		[return 返回值]; 
	  	}
throws的特点
  • 1.抛出异常的处理方法千万不能抛出给JVM处理[主方法]
  • 2.一般情况,我们把锅甩给方法,这样使用者在掉方法时出错,报错的为方法行,而不是main
  • 3.如果一个方法抛出的是一个编译时异常,那么调用者必须处理
  • 4.如果一个方法抛出的是一个运行时异常,可以处理也可以不处理,建议处理,提高程序的安全性
  • 5.子类重写的方法声明的异常范围小于父类(和方法权限修饰符相反) 子:RuntimeException 父:Exception
  • 6.throws表示一种异常发生的可能性,可以声明多个异常类.
    前4点的代码
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try{
			method();//把锅甩给方法,调用才报错
		}catch(Exception e){
			e.printStackTrace();
		}
		System.out.println("haha  bug");//程序依旧执行
	}
	public static void method()throws Exception{//这个异常是运行时异常,可不处理
		int a[]=new int[3];
		a[3]=10;
		
	}

后两点代码(声明异常)

//当子类throws Exception 会报错   改为RuntimeException的子类或本身即可
class Fat{
	public void show()throws RuntimeException,ParseException//声明多个异常类
{
		System.out.println("运行时异常");
	}
}
class son extends Fat{
	public void show()throws RuntimeException{
		System.out.println("运行时异常的本身或者子类");
	}	
}

throw处理异常

有了throws关键字为什么还要学习throw?
之前我们处理异常都可以try catch,throws,或者规避错误
但对异常进行更灵活的操作,比如在异常部分添加自己定义的输出语句,或者有异常则转发到其他页面要用到throw

throws处理异常的格式:

throw 异常对象;

		//throw new Exception("除数不能为0");  //方法1
		Exception n=new Exception("出书不为0");//throw抛出的是异常对象
		throw n;//方法2
案例:
	public static void method() throws Exception{
		int a=10;
		int b=0;
		if(b==0)//throw在方法体内出现
		{
			//throw new Exception("除数不能为0");  //方法1
			Exception n=new Exception("出书不为0");//throw抛出的是异常对象
			throw n;//方法2
		}	
		Runtime.getRuntime().exit(0);
		System.out.println(a/b);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			method();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("asd");//依然可以执行
	}
打印信息:
	java.lang.Exception: 出书不为0
	asd
	at com.ljx.exception_te.Exception_04.method(Exception_04.java:26)
	at com.ljx.exception_te.Exception_04.main(Exception_04.java:36)

自定义异常类

自定义异常格式

1、运行时异常 继承 RuntimeException
编译时异常 继承 Exception
2、书写两个构造方法
无参构造方法
带 message 参数的构造方法
案例:分数必须在0~100分之间
需求: 自定义分数异常

public class Exception_06 {

	public static void main(String[] args) {	
		double score=474;
		Teacher t=new Teacher();
		try {
			t.checkScore(score);//当成绩不在0-100之间时抛出异常
		} catch (ScoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}
class Teacher{
	public boolean checkScore(double s) throws ScoreException{
		if(s>100||s<0)
		throw new ScoreException("分数异常");//异常打印的行数
		return true;	
	}
}
class ScoreException extends Exception{
	private static final long serialVersionUID = 1L;
	public ScoreException(){
		
	}
	public ScoreException(String s){
		super(s);
	}	
}
打印结果:
	com.ljx.exception_te.ScoreException: 分数异常
	at com.ljx.exception_te.Teacher.checkScore(Exception_06.java:34)
	at com.ljx.exception_te.Exception_06.main(Exception_06.java:23)

异常的笔试题

代码题
public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(show());
	}
	public static int show(){
		int x=1;
		try{
			x++;
			return x++;
		}finally{
			++x;
			System.out.println(x);
		}	
	}

解析:在try语句中,在执行return语句时,要返回的结果2已经准备好了 ,接着x++=3
此时,程序转到finally执行。
在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果(使用栈保存返回值)
打印时先执行show方法,打印4 后执行main打印2

关于finally

finally修饰的代码块一定会被执行
除非在执行到finally之前程序异常退出或者调用了系统退出的方法Runtime.getRuntime().exit(0);或者System.exit(0);
finally的作用:
* finally用于释放资源,在IO流操作和数据库操作中会见到。
IO流的连接,数据库的连接,网络连接等等

finally相关的面试题
简述final,finally和finalize的区别。
参考final关键字篇

断言

assert <boolean表达式>
当表达式为True程序继续执行

捕获控制台的异常信息,保存在文件中

Str转成int 出现异常,写个函数保存出现异常信息,(异常信息中包含时间)要求可追加

import java.io.*;
import java.sql.Date;
import java.text.*;
import java.util.Calendar;
import java.util.Properties;

public class T_10 {
	 
	public static void main(String[] args) throws FileNotFoundException  {
		String string="123a";
		String s="exception.log";
		try {
			int ints =Integer.parseInt(string);
		} catch (NumberFormatException e) {
			e.printStackTrace();//这个函数也可以传入一个OutputStream类型的对象参数
			//改变一下标准的输出设备,利用万能流printStream将标准输出写入文件
			System.setOut(new PrintStream(new FileOutputStream(new File(s),true),true));
			e.printStackTrace(System.out);
		}
				
		//系统信息的持久化
		//	outputSystemInfo();
		//加入时间:
		writeInFile(s);
	}
	private static void writeInFile(String s) {
		//加入时间:
		Calendar calendar=Calendar.getInstance();
		Date date=new Date(calendar.getTimeInMillis());
		
		String string=new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss").format(date);
		try {
			BufferedWriter bo = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(s),true)));
			bo.write(string);
			bo.newLine();
			bo.flush();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	//将系统信息持久化的方法
	public static void outputSystemInfo() {
		Properties pro=System.getProperties();
		try {
			System.setOut(new PrintStream("properties.log"));
		} catch (FileNotFoundException e) {
			System.out.println("创建文件失败");
		}
		pro.list(System.out);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值