Java学习笔记(41)—— 异常

这里将自己学习java及其应用的一些笔记、积累分享一下,如果涉及到了文章、文字侵权,请联系我删除或调整。


一、异常

1.1 概述

  • 异常:封装错误信息的对象
  • 错误信息:

类型

提示消息

行号

1.2 异常的继承结构

Throwable

      |- Error 系统级错误

      |- Exception 异常,可修复的错误

                   |- 其他Exception

                   |- RuntimeException

                                 |- NullPointerException

                                 |- ArrayIndexOutOfBoundsException

                                 |- ArithmeticException

                                 |- NumberFormatException

                                 |- ClassCastException

                                 |- ClassNotFoundException

                                 |- ...

1.3 异常捕获

下面介绍3中常见的异常捕获的代码结构:

  • 第一种:

try {

} catch(AException e){

     ……

} catch(BException e) {

    ……

} catch(父类型Exception e) {

   ……

} finally {

     不管出错还是不出错都会执行。一般在此,会做一些资源管理的操作,防止资源泄露。
            finally 不论是否有break,reutrn等语句,它都会执行

}

  • 第二种:

try {

} catch() {

      ……

}

  • 第三种:

try {

} finally {

   ……

}

1.4 练习:异常-异常捕获

package 异常;

import java.util.Scanner;

public class Test1_trycatch {
	public static void main(String[] args) {
		while (true) {
			// 捕获异常
			try {
				f();
				break;
			} catch (ArrayIndexOutOfBoundsException e) {
				System.out.println("索引越界了,请输入两个整数!");
			} catch (NumberFormatException e) {
				System.out.println("输入数据格式有误!");
			} catch (ArithmeticException e) {
				System.out.println("0不能作除数!");
			} catch (Exception e) {
				System.out.println("索引没越界,输入数据格式也对,0也没做除数,可是就是有问题,你气不气!");
			} finally {
				// 一般做一些资源管理,防止资源泄露
				// finally 不论是否break,reutrn等都会执行
				System.out.println("Finally被执行了!");
			}
		}
	}

	private static void f() {
		/*
		 * "345,543"拆分 => ["345","543"] 0 1 分别将下标1与下标2解析为整数并相除
		 */

		System.out.println("输入两个整数,例如格式345,543:");
		String s = new Scanner(System.in).nextLine();

		String arr[] = s.split(",");
		int n1 = Integer.parseInt(arr[0]);
		int n2 = Integer.parseInt(arr[1]);
		int r = n1 / n2;

		System.out.println(r);
	}
}

二、throws

2.1 概述

  • throws用于在方法上设置异常的抛出管道,例如:

void f() throws X,Y,Z {

}

  • 所有方法上都有默认的异常管道RuntimeException

2.2 练习:thows

package 异常;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;

public class Test2_throws {
	// throws设置管道
	public static void main(String[] args){
		try {
			f();// f()也会进一步throw解析异常与IO异常,也需捕获或设置管道
		} catch (ParseException e) {
			System.out.println("日期格式输出!");
			e.printStackTrace();// 打印完整异常信息
		} catch (IOException e) {
			System.out.println("无法创建文件!");
			e.printStackTrace();
		}
	}

	private static void f() throws ParseException, IOException {
		/*
		 * 输入一个字符串日期 依据字符串"2019-3-16"得到日期毫秒值
		 * 
		 * 1.将字符串变成Date对象, SimpleDateFormat转变对象 .parse("2019-3-16"),解析为毫秒值;
		 */
		System.out.println("输入日期(年-月-日):");
		String s = new Scanner(System.in).nextLine();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date dec = sdf.parse(s);// 会抛一个解析异常,需要管道或捕获
		long t = dec.getTime();

		File f = new File("d:/" + t + ".txt");
		f.createNewFile();// 会抛一个IO异常,需要管道或捕获
	}
}

三、catch和throws

3.1 概述

  • 异常处理只有两种方式: catch 和 throws
  • 异常处理,必须二选一
  • Java语法,强制开发者事先考虑异常如何处理
  • 刚接触软件开发的初学者,可能会捕获,但不处理异常

​​​​​​​​​​​​​​try {

     ...

} catch(Exception e) {

}

3.2 catch throws怎么选(很多博文、大佬文章都聊过这个话题)

底层异常,建议应该向前抛到前面处理

经验少时,不知道该在什么位置捕获处理,应该选择 throws

四、throw

4.1 概述

  • throw:人为手动抛出异常,执行异常的抛出动作
  • throw 可类比成 return

​​​​​​​​​​​​​if(逻辑错误) {

        AException e = new AException("提示消息");

       throw e;

}

4.2 练习:throw

package 测试throw;

import java.util.Scanner;

public class Test3 {
	public static void main(String[] args) {
		f();
	}

	private static void f() {
		/*
		 * 23.25/0 Infinity
		 */
		System.out.println("输入两个浮点数:");
		double a = new Scanner(System.in).nextDouble();
		double b = new Scanner(System.in).nextDouble();
		try {
			double r = divide(a, b);
			System.out.println(r);
		} catch (ArithmeticException e) {
			System.out.println("不能除0!");
			//e.printStackTrace();//打印完整异常
		}
	}

	private static double divide(double a, double b) {
		if(b == 0) {
			ArithmeticException e = new ArithmeticException("/ by zero");
			throw e; //return e;
		}
		return a/b;
	} 
}

五、异常包装

5.1 概述

  • 将捕获的异常,包装成另一种类型,再抛出

try {

     ……

} catch(AException e) {

      throw new BException(e);

}

5.2 使用场景

  • 对于不能抛出的异常类型,可以将其包装成能抛出的类型,再抛
  • 异常简化——把多种类型异常,简化成一种

​​​​​​​​​​​​​​​​​​​​​5.3 方法重写 Override

  • 重写方法时,异常管道,不能比父类方法多

​​​​​​​​​​​​​​​​​​​​​5.4 练习:异常包装

package 异常;

import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Test1_异常包装 {
	public static void main(String[] args) {
		f();
	}

	private static void f() {
		/*
		 * 对一组日期字符串排序 "2019-3-1" "2019-3-4" "2019-3-6" "2019-3-11" "2019-3-18" "2019-3-25"
		 */
		ArrayList<String> list = new ArrayList<String>();
		Collections.addAll(list, "2019-3-1", "2019-3-4", "2019-3-6", "2019-3-11", "2019-3-18", "2019-3-25"); // 一次性添加多个元素
		// for-each循环遍历,本质是迭代器
		for (String s : list) {
			System.out.println(s);
		}
		System.out.println("--------------------------------");

		Collections.sort(list);// 按字符串的字符编码排序
		for (String s : list) {
			System.out.println(s);
		}
		System.out.println("--------------------------------");

		Collections.sort(list, new Comparator<String>() {// 匿名类的比较器对象
			@Override
			public int compare(String o1, String o2) {
				// 把日期字符串变成Date对象:2019-3-12 => Date对象
				// SimpleDateFormat
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				try {
					Date d1 = sdf.parse(o1);
					Date d2 = sdf.parse(o2);
					return d1.compareTo(d2);
				} catch (ParseException e) {//此处无法添加异常管道throws,因为子类不能超出父类的管道范围
					throw new IllegalArgumentException(e);// 非法参数异常,将ParseException包装成IllegalArgumentException抛出
				}
			}
		});

		for (String s : list) {
			System.out.println(s);
		}
		System.out.println("--------------------------------");
	}

}

六、自定义异常

6.1 概述

  • 现有异常类型,不能表示业务中遇到的所有错误情况,这时就需要根据业务需要,自定义异常类型了,例如:

转账错误    ZhuanZhangShiBaiException

用户名       UsernameNotFoundException

密码错误   WrongPasswordException

  • 自定义异常

起一个合适的类名

选一个合适的父类

添加合适的构造方法

6.2 练习:自定义异常

package 异常;

import java.util.Scanner;

public class Test2_自定义异常 {
	public static void main(String[] args) {
		f();
	}

	private static void f() {
		System.out.println("用户名:");
		String name = new Scanner(System.in).nextLine();
		
		System.out.println("密码:");
		String pass = new Scanner(System.in).nextLine();
		
		try {
			login(name,pass);
			System.out.println("欢迎登陆!");
		} catch (UsernameNotFoundException e) {
			System.out.println("用户名错误!");
		}catch (WrongPasswordException e) {
			System.out.println("密码错误!");
		}
	}

	private static void login(String name, String pass) throws WrongPasswordException, UsernameNotFoundException {
		if(name.equals("admin")&&pass.equals("admin")) {
			return;
		}else if(name.equals("admin")) {
			throw new WrongPasswordException();
		}else if(pass.equals("admin")) {
			throw new UsernameNotFoundException();
		}
	}
}
package 异常;

public class UsernameNotFoundException extends Exception{
	// Exception没有默认管道,必须添加管道才能抛出
	// 参考父类构造方法,添加子类的构造方法,alt + shift + s
	public UsernameNotFoundException() {
		super();
	}

	public UsernameNotFoundException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public UsernameNotFoundException(String message, Throwable cause) {
		super(message, cause);
	}

	public UsernameNotFoundException(String message) {
		super(message);
	}

	public UsernameNotFoundException(Throwable cause) {
		super(cause);
	}	
}
package 异常;

public class WrongPasswordException extends Exception{

	public WrongPasswordException() {
		super();
	}

	public WrongPasswordException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public WrongPasswordException(String message, Throwable cause) {
		super(message, cause);
	}

	public WrongPasswordException(String message) {
		super(message);
	}

	public WrongPasswordException(Throwable cause) {
		super(cause);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值