异常

异常:

1、 异常处理概述

2、 异常的捕获和处理

3、 Java异常API

异常处理概述:

异常是方法的意外结果。

1、使用返回值状态标识异常

这个方法有很多坏处:首先,返回值可以是任意的,需要调用API的程序自己判断并解释返回值的含义;没有机制保证异常一定会得到处理,需要检测返回值并处理异常情况;这种方式还会造成程序代码冗长。

2、异常处理机制

3、Throwable、Error和Exception

Java异常结构中定义有Throwable类,Exception和Error是其派生的两个子类。其中Exception是可以修复的异常,Error表示Java运行时环境出现的错误,例如:JVM内存资源耗尽等等,是不可恢复的错误。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Demo {
	public static void main(String[] args){
		//从控制台输入一个时间(yyyy-M-d)
		//parse(String)方法就声明了异常
		//如果输入的字符串格式不正确,就抛出异常
		//处理这个异常:规则,如果输入时间不正确,就使用当前系统时间作为输入结果。
		Scanner in=new Scanner(System.in);
		System.out.println("输入日期:");
		String str=in.nextLine();
		
		SimpleDateFormat fmt=new SimpleDateFormat("yyyy-M-d");
		Date date;
		try {
			//parse方法就是有异常声明的方法
			//如果parse执行一旦出现异常,将跳到catch执行
			date=fmt.parse(str);//会抛出异常
			System.out.println("解析正确!");
		}catch(ParseException e) {
			System.out.println("解析错误!"+e.getMessage());
			date=new Date();
		}
		
		//Java编译器进行异常的语法检查,如果调用了有异常抛出的方法,就必须处理异常,
		//而异常的处理方式有两种:1、使用try-catch处理,2、将异常抛出。
		//违反了规则,将有编译错误,现在就是编译错误。
		System.out.println(fmt.format(date));
	}
}

4、Try-catch

Try程序块若是有异常发生,程序的运行便中断,并抛出“异常类所产生的对象”,抛出的对象如果属于catch()括号内欲捕获的异常类,catch则会捕捉此异常,然后进入到catch块里继续执行。

每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常。Catch捕获的异常类型由上至下的捕获异常类型的顺序应该是子类到父类。子类型捕获异常在前,父类型捕获异常在后,这样的顺序依次捕获,否则编译不通过。

5、Finally的作用:

无论try所指定的程序块中是否抛出异常,finally所指定的代码都要被执行,通常在finally语句中可以进行资源的释放工作,如关闭打开的文件、删除临时文件等。

public class testFinally {

	public static void main(String[] args) {
		System.out.println(t("55"));
		System.out.println(t(""));//空字符串,长度为0
		System.out.println(t(null));//字符串为空字符串

	}
	public static int t(String str) {
		try {
			char c=str.charAt(0);//'5'
			return c-'0';//'5'-'0'
		}catch(NullPointerException e){
			return -2;
		}catch(RuntimeException e){//是StringIndexOutofBoundsException的父类
			return -1;
		}finally {//无论try是否发生异常都会执行的代码
			//结果:100 100 100
			//每次return后的结果都在缓冲区,然后finally一执行,缓冲区中的内容就被改写了,所以返回三个100
			//通常不能这么写
			//在最后执行的代码
			return 100;
		}		
	}
}

6、throw关键字

当程序发生错误而无法处理的时候,会抛出对应的异常对象,除此之外,在某些时刻,您可能会想要自行抛出异常,例如在异常处理结束后,再将异常抛出,让下一层异常处理块来捕捉,若想要自行抛出异常,您可以使用“throw”关键字,并生成指定的异常对象后抛出。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class testThrow {
	public static void main(String[] args) {
		String id="12345619990101001x";
		try {
			Date date=dayOfBirth(id);
			System.out.println(date);
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//根据一个人的身份证号码,计算出生日
	//throws:表示这个方法在执行期间可能有意外,如果没有意外,正常返回Date
	//throws:用于在方法上声明异常
	//throw:用于在方法中如果出现意外情况抛出异常
	//throw会使方法结束,提前返回
	public static Date dayOfBirth(String id) throws Exception,ParseException{
											 //处理不了的情况就抛掉
		if(id==null) {
			throw new Exception("有木有搞错!");
		}
		if(!id.matches("^\\d{17}[0-9Xx]$")) {
			throw new Exception("还有错误!");
		}
		String s=id.substring(6, 6+8);
		SimpleDateFormat fmt=new SimpleDateFormat("yyyyMMdd");
		Date date=fmt.parse(s);//parse作用是将时间转换为java时间,处理异常ParseException
		return date;
	}
}

总结:

1、异常:一段代码的意外结果,不是正常结果

2、学习异常:对于意外结果的处理语法和处理规范

3、关键字:

    try{}catch{}finally{}:用于捕获异常

    throws:在方法(构造器)上声明这个方法在执行期间可能出现意外结果。

    throw:在软件中如果出现了意外情况,就抛出异常对象,使方法异常结束。

4、编译规则:

    1、如果调用了有异常(可检查异常)抛出的方法,就必须处理异常,否则有编译错误,有两种处理办法。

        A、try捕获异常

        B、使用throws声明抛出异常

    2、处理习惯:上面两种处理办法选择哪种处理办法

        A、如果是代码中能够处理的异常,就尽量处理,如果不能处理一定抛出。要依据业务规则处理。

        B、异常不能随便丢弃。

        C、打印异常中方法调用跟踪栈

            e.printStackTrace()

            出异常好找到位置

Java异常:

1、Java异常

    Java异常分为可检测异常和非检测异常

      1、 可检测异常

        可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译。

    2、 非检测异常

        非检测异常不遵循处理或声明规则。在产生此类异常时,不一定非要采取任何适当操作,编译器会检查是否已经解决了这样一个异常。

2、RuntimeException

这类异常属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译器检查与处理或声明规则的限制。

代码见:Day10.TestCase中的testInteger()

3、异常的分类(继承关系)

Throwable 父类是Object

   |---Error

   |    |---OutOfMemoryError

   |    |---…

   |---Exception

        |---IOException检查异常

        |      |---FileNotFoundException

        |      |---EOFException

        |---CopyException 自定义异常

        |---RuntimeException  非检查异常,编译器不检查

        |      |---NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当的格式时,抛出该异常

        |      |---NullPointerException引用变量值为空

        |      |---ArrayIndexOutOfBoundsException 当使用的数组下标超过数组允许范围时,向负方向越界,抛出该异常

        |      |---IndexOutOfBoundsException向正方向越界

        |      |---StringIndexOutOfBoundsException

        |      |---IllegalArgumentException抛出的异常表明向方法传递了一个不合法或不正确的参数

        |      |---ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常

public void testNullPointer() {
		String[] names=new String[5];
		           //{null,null,null,null,null}自动初始化为null
		System.out.println(names[0].length());//出现NullPointerException,因为names[0]是null
		System.out.println(names.length);//数组的长度,是5
	}
public void testIndexOutBounds() {
		ArrayList<String> names=new ArrayList<String>();
		System.out.println(names.size());//0
		System.out.println(names.get(-1));//ArrayIndexOutOfBoundsException,负方向越界
		System.out.println(names.get(1));//IndexOutOfBoundsException,正方向越界
	}
public void testClassCast() {
		Object o=4.5;//自动包装为Double类型的对象
		//会出现ClassCastException,因为在运行期间不能将Double类型强制转换为Integer类型
		int i=(Integer)o;//ClassCastException
	}

Exception常用API

1、 printStackTrace

原则上但凡遇到异常都要打印这个方法执行的堆栈。

Throwable中定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容。}

2、 getMessage

Throwable中定义了一个方法可以得到有关异常事件的信息。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class TestprintStackException {

	public static void main(String[] args) {
		//从控制台输入日期:
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入日期:");
		String in=sc.nextLine();
		SimpleDateFormat fmt=new SimpleDateFormat("yyyy-M-d");
		try {
			Date d=fmt.parse(in);//转换为java时间
		} catch (ParseException e) {
			System.out.println(e.getMessage());//返回异常的信息
			e.printStackTrace();
			//如果不加上面这句,就不能简单粗暴的捕获并丢弃异常!
		}		
	}
}

3、 getCause

一个异常由另一个异常引起的时候,使用getCause来获取原因

自定义Exception

1、 用户自定义异常:

1、要从Exception继承

2、要增加构造器,与父类型一样的构造器

3、一般不需要填写任何方法,父类型继承的方法够用了

	
	/**
	 * 复制文件
	 * @param src
	 * @param dst
	 * @throws CopyException 复制失败时候抛出
	 */
	public static void copy(String src,String dst) throws CopyException{
		//CopyException是自己定义的异常
		File srcFile=new File(src);
		File dstFile=new File(dst);
		if(!srcFile.exists()) {
			throw new CopyException("木有源文件"+src);
		}
		if(srcFile.isDirectory()) {
			throw new CopyException("源文件是目录!");
		}
		if(dstFile.exists()&&dstFile.isDirectory()) {
			dstFile=new File(dstFile,srcFile.getName());
		}
		//目标文件是文件的时候,就把内容复制
		FileInputStream in=null;
		FileOutputStream out=null;
		try {
			in=new FileInputStream(srcFile);//把文件打开
			out=new FileOutputStream(dstFile);
			byte[] buf=new byte[1024*8];
			int n;
			while((n=in.read())!=-1) {
				out.write(buf, 0, n);
			}
		}catch(IOException e) {
			e.printStackTrace();
			//抛出带有根本原因e的CopyException异常
			throw new CopyException("复制失败!",e);
		}finally {
			try {
				if(in!=null) {
					in.close();
				}
				if(out!=null) {
					out.close();
				}
			}catch(IOException e) {
				//在打开或关闭文件时候的异常,不需要抛出的异常,这个异常没有办法处理!
				e.printStackTrace();
			}
			
		}
		
	}

}
        public void testCopy() {
		String src="E:/1.rar";
		String dst="Z:/";//Z盘是光驱,只能读不能写
		//以上测试案例,会产生有根本原因的异常
		try {
			FileUtils.copy(src, dst);
		} catch (CopyException e) {
			e.printStackTrace();
			System.out.println(e.getCause());
			//根本原因:Caused by: java.io.FileNotFoundException: Z:\ (设备未就绪。)
		}
	}

方法的异常声明方式:有两种

1、利用返回值来说明异常

    int read()方法

    正常返回:0~255

    异常情况:当返回-1时候,表示读取文件EOF

2、利用异常声明,说明异常情况

    1、reatInt()方法:

        正常返回:文件中连续4个byte拼接为一个整数

        异常情况:当读取到文件末尾或者不够4个byte抛出异常EOFException

public void testReadInt() throws Exception {
		String file="int.bin";
		RandomAccessFile raf=new RandomAccessFile(file,"rw");//可以写完不关闭然后读取
		for(int i=100;i<500;i+=100) {
			raf.writeInt(i);//把4个整数写到文件中
		}
		raf.seek(0);//移动文件指针到文件头
		try {
			while(true) {//循环使用异常结束
				int i=raf.readInt();//读取整数
				System.out.println(i);
			}
		}catch(EOFException e) {
			System.out.println("读取结束!");
		} 
		raf.close();
	}
}

    2、readObject()方法:

        正常返回:返回一个对象

        异常情况:抛出异常EOFException 读取到文件末尾了

总结:

1、 异常:

异常:异常的处理规则选择依赖于具体的业务场景!

原则:能够处理尽量处理,不能处理一定抛出。

处理:try catch

抛出:throws 在方法声明,throw 抛出异常对象

2、 异常分类:

        1、 Error:系统不可恢复的错误:是应用程序没有机会处理的错误,一旦出现当前系统已经崩溃掉了。

        2、 Exception:系统可恢复的异常:应用程序可以编程处理,处理以后可以继续执行。

3、 RuntimeException

非检查异常:Java编译器会忽略掉这类(子类)异常的调用和抛出语法检查!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值