稳稳当当学java之枚举和异常(15)

第十七章 枚举和异常

1.作业回顾

//1,写一个方法判断字符串是否对称。对称的字符串。"abcdefgfedcba"
public class Day16HomeWork {
	
	public static boolean f1(String str) {
		char[] arrs = str.toCharArray();
		for (int i = 0; i < arrs.length / 2; i++) {
			if(arrs[i] != arrs[arrs.length - 1 - i]) {
				return false;
			}
		}
		return true;
	}
	
	public static void main(String[] args) {
		System.out.println(f1("abcdefgfedcba"));//true
		System.out.println(f1("abcddcba"));//true
		System.out.println(f1("abcccccccccca"));//false
	}
}
//2,写一个方法将字符串中的大写字符转换为小写字符,小写字符转换为大写字符。 
//String f1(String str)。abcdeFGH--->ABCDEfgh
public class Day16HomeWork2 {
	
	public static String f1(String str) {
		char[] arrs = str.toCharArray();
		for (int i = 0; i < arrs.length; i++) {
			if (arrs[i] >= 97 && arrs[i] <= 122) {
				arrs[i] = (char) (arrs[i] - 32);
			} else if(arrs[i] >= 65 && arrs[i] <= 90){
				arrs[i] = (char) (arrs[i] + 32);
			}else {
				//do nothing
			}
		}
		return new String(arrs);
	}
	public static void main(String[] args) {
		System.out.println(f1("abcdeFGH"));//ABCDEfgh
	}
}

2.枚举

在Java编程语言中,可以使用enum关键字定义枚举类型。

例如,可以将星期几的枚举类型指定为:

//使用enum关键字声明一个枚举类
enum Day{
    //枚举类的值,类型是Day
	SUNDAY,
	MONDAY,
	TUESDAY,
	WEDNESDAY,
	THURSDAY,
	FRIDAY,
	SATURDAY,
}
public class Day1702 {
	//枚举是一种特殊的类型,它的值是一组预定义的常量。
	//d是一个枚举类型的变量,它的类型是Day,Day.MONDAY是一个枚举值
	public static void main(String[] args) {
		Day d = Day.SUNDAY;
		switch (d) {
		case SUNDAY:
			System.out.println("星期日");
			break;
		case MONDAY:
			System.out.println("星期一");
			break;
		case TUESDAY:
			System.out.println("星期二");
			break;
		case WEDNESDAY:
			System.out.println("星期三");
			break;
		case THURSDAY:
			System.out.println("星期四");
			break;
		case FRIDAY:
			System.out.println("星期五");
			break;
		case SATURDAY:
			System.out.println("星期六");
			break;
		}	
	}
}

所有的枚举类都继承于java.lang.Enum类。

编译器在创建枚举时会自动添加一些特殊方法。

public class Day1703 {
	public static void main(String[] args) {
		Day d = Day.SUNDAY;
		//所有的枚举都隐式继承于java.lang.Enum,java.lang.Enum继承于java.lang.Object
		System.out.println(d instanceof Object);//true
		System.out.println(d instanceof Enum);//true

		//遍历枚举 
		//每一个枚举类都有一个静态的values方法,它是编译器加的 
		//静态的values方法按照声明的顺序返回一个包含所有枚举值的数组
		Day[] arr = Day.values();
		for(Day day : arr) {
			System.out.println(day);
		}
		
		System.out.println("******************");
		
		//静态的valueOf(String)方法,将字符串转换成枚举值,它是编译器加的
		Day d1 = Day.valueOf("SUNDAY");//将字符串SUNDAY转换为Day.SUNDAY
		System.out.println(d1);//SUNDAY
		
		//枚举值转换为字符串 
		//name(),toString()是实例方法,继承于java.lang.Enum
		System.out.println(d1.name());//将Day.SUNDAY转换为字符串SUNDAY
		System.out.println(d1.toString());//将Day.SUNDAY转换为字符串SUNDAY
		
		System.out.println("******************");
		
		//获取枚举的序号
		System.out.println(Day.SUNDAY.ordinal());//0
		System.out.println(Day.MONDAY.ordinal());//1
		
		//枚举的比较
		Day m1 = Day.MONDAY;
		Day m2 = Day.MONDAY;
		System.out.println(m1 == m2);//true
		System.out.println(m1.equals(m2));//true
	}
}

3.异常的基本概念

main方法将抛出一个异常,因为在一个null对象上调用了toString方法。

public class Day1704 {
	public static void main(String[] args) {
		String str = null;
		//在一个null对象上调用方法会导致NullPointerException,空指针异常
		str.toString();
		//下面的语句不会得到执行,因为异常会导致程序执行终止
		System.out.println("hello");
	}
}

3.1 异常的传播

public class Day1705 {
	
	public static void method1() {
		method2();
	}
	
	public static void method2() {
		String str = null;
		str.toString();
	}
	
	public static void main(String[] args) {
		method1();
	}
}

查看栈的轨迹,method2中抛出的异常传递到method1,然后传递到main。

使用try catch处理异常。

public class Day1705 {
	
	public static void method1() {
		method2();
		System.out.println("method1");
	}
	
	public static void method2() {
		String str = null;
		//尝试执行try代码块,如果捕获到了NullPointerException,就执行catch块
		try {
			str.toString();
			System.out.println("hello");//不会执行
		}catch(NullPointerException e) {
			System.out.println("捕获到异常");
		}
		System.out.println("method2");
	}
	
	public static void main(String[] args) {
		method1();
		System.out.println("main");
	}
}

因为method2处理了异常,因此异常不再传递给method1。因此method1和main方法将不受method2中异常的任何影响,打印语句将会执行。这是异常处理的基本概念。但是,method2中抛出异常后的语句将不会执行。

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

//异常是预先的处理机制
public class Day1706 {
	public static void main(String[] args) {
		System.out.println("请输出日期字符串:yyyy-MM-dd");
		Scanner s = new Scanner(System.in);
		//用户输入的日期字符串
		String str = s.nextLine();
		//yyyy-MM-dd
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			//如果str和预期额格式不匹配,将解析错误,并抛出ParseException
			Date date = sdf.parse(str);
			System.out.println(date);
		} catch (ParseException e) {
			System.out.println("格式不正确,请检查");
		}
	}
}

3.2 使用finally执行代码

class connection{
	public void open() {
		System.out.println("打开连接");
	}
	public void close() {
		System.out.println("关闭连接");
	}
}

public class Day1707 {
	
	public static void f(connection con) {
		try{
			con.open();//打开连接
			//使用连接做一些工作
			String str = null;
			str.toString();
		}catch(NullPointerException e){
			System.out.println("捕获异常");
		}finally {//不管有没有异常产生,finally块总是会执行
			con.close();//关闭连接
		}
	}
	public static void main(String[] args) {
		connection con = new connection();
		f(con);
	}
}

即使在try和catch块中使用了return语句,finally依然会执行

class connection{
	public void open() {
		System.out.println("打开连接");
	}
	public void close() {
		System.out.println("关闭连接");
	}
}

public class Day1707 {
	
	public static void f(connection con) {
		try{
			con.open();//打开连接
			return;
		}catch(NullPointerException e){
			System.out.println("捕获异常");
		}finally {//即使在try和catch块中使用了return语句,finally依然会执行
			con.close();//关闭连接
		}
	}
	public static void main(String[] args) {
		connection con = new connection();
		f(con);
	}
}

不带catch的try和finally也是允许的,但会抛出异常。

class connection{
	public void open() {
		System.out.println("打开连接");
	}
	public void close() {
		System.out.println("关闭连接");
	}
}

public class Day1707 {
	
	public static void f(connection con) {
		try{
			con.open();//打开连接
			String str = null;
			str.toString();//出现异常,执行finally块,然后将异常抛出给调用者
		}finally {
			con.close();//关闭连接
		}
	}
	public static void main(String[] args) {
		connection con = new connection();
		f(con);
		System.out.println("main");//不会执行
	}
}

4.异常体系

Throwable是异常体系的最顶层类。Error(错误)和Exception(异常)继承于Throwable类。
在这里插入图片描述
当java虚拟机中发生动态链接故障,或其他硬件故障时,虚拟机会抛出一个Error。程序通常不会捕获或抛出Error。当Error发生时,在代码中没法做任何处理。比如StackOverFlowError和OutOfMemoryError。 在代码中不能处理Error,但是可以处理Exception。大多数程序抛出并捕获Exception类派生的对象。一个Exception表示发生了问题,但这不是一个严重的系统问题。大多数程序都会抛出并捕获Exceptions而不是Errors。

java平台定义了Exception类的许多子类。这些子类代表可能发生的各种类型的异常。例如ParseException表示解析出现异常,NullPointerException表示在一个null对象上调用了方法。

Exception分为两种:运行时异常(RuntimeException)和受检查异常(CheckedException)。

RuntimeException和所有继承于RuntimeException的子类称为运行时异常。运行时异常的例子:NullPointerException。 Exception的子类除了运行时异常,其他的都是受检查异常。受检查异常的例子: ParseException。

编译能通过,但是运行时发生的异常是运行时异常,NullPointerException。

编译不能通过,需要处理的异常是受检查异常,ParseException。

public class Day1708 {
	
	public static void f1() {
		//NullPointerException是运行时异常,编译时不会提醒需要捕获
		String str = null;
		str.toString();
	}
	
	public static void f2() {
		//yyyy-MM-dd
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		//在编译时提醒需要捕获的是受检查异常
		try {
			Date date = sdf.parse("12hji6");
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {

	}
}

运行时异常不需要捕获,因为产生运行时异常是因为代码编写问题,可以通过规范代码(增加条件判断)来避免运行时异常的发生。

public static void f1(String str) {
	//通过规范代码(增加条件判断)来避免运行时异常的发生
	if(String str != null;){
        str.toString();
	}
}

受检查异常需要在程序中做处理,因为这是没办法避免的。比如ParseException,转换的字符串可能来自于客户的输入,这个输入是事先无法预期的。

5.自定义异常

如果需要定义运行时异常,那么需要继承RuntimeException。

如果需要定义受检查异常,需要继承Exception。

5.1 使用运行时异常

//银行账户
public class Amount {
	//货币类型
	private String currency;
	//金额
	private int amount;
	
	public Amount(String currency, int amount) {
		super();
		this.currency = currency;
		this.amount = amount;
	}
	
	public String getCurrency() {
		return currency;
	}
	public void setCurrency(String currency) {
		this.currency = currency;
	}
	public int getAmount() {
		return amount;
	}
	public void setAmount(int amount) {
		this.amount = amount;
	}
	
}
//运行时异常 
//货币类型不匹配异常
public class CurrencyDoNotMatchException extends RuntimeException{
	
	//message代表异常信息
	public CurrencyDoNotMatchException(String message) {
		super(message);
	}
}
public class AmountAdder {
	
	public static Amount add(Amount m1, Amount m2) {
		if(m1.getCurrency().equals(m2.getCurrency())) {
			return new Amount(m1.getCurrency(), m1.getAmount() + m2.getAmount());
		}else {
			//如果账户类型不匹配,就抛出一个CurrencyDoNotMatchException类的实例
			throw new CurrencyDoNotMatchException("货币类型不匹配:m1:" + m1.getCurrency() + ", m2:" + m2.getCurrency());
		}
	}
	
	public static void main(String[] args) {
		AmountAdder.add(new Amount("DOLLAR", 5),new Amount("CNY", 5));
	}
}

5.2 使用受检查异常

//受检查异常 
//货币类型不匹配异常
public class CurrencyDoNotMatchException extends Exception{
	
	//message代表异常信息
	public CurrencyDoNotMatchException(String message) {
		super(message);
	}
}
public class AmountAdder {
	
	//此方法声明其可能抛出一个CurrencyDoNotMatchException
	public static Amount add(Amount m1, Amount m2) throws CurrencyDoNotMatchException {
		if(m1.getCurrency().equals(m2.getCurrency())) {
			return new Amount(m1.getCurrency(), m1.getAmount() + m2.getAmount());
		}else {
			//如果账户类型不匹配,就抛出一个CurrencyDoNotMatchException类的实例
			throw new CurrencyDoNotMatchException("货币类型不匹配:m1:" + m1.getCurrency() + ", m2:" + m2.getCurrency());
		}
	}
    
	//main方法处理的方式有两种
	//1.抛出异常
//	public static void main(String[] args) throws CurrencyDoNotMatchException {
//		AmountAdder.add(new Amount("DOLLAR", 5),new Amount("CNY", 5));
//	}
	
	//2.捕获异常
	public static void main(String[] args) {
		try {
			AmountAdder.add(new Amount("DOLLAR", 5),new Amount("CNY", 5));
		} catch (CurrencyDoNotMatchException e) {
//			System.out.println("捕获到异常,货币类型不匹配");
			
			//打印异常调用栈的信息(实际中常用)
			e.printStackTrace();
		}
	}
}
import java.io.IOException;
import java.text.ParseException;

public class Day1709 {
	
	//f1方法声明其将抛出多个异常
	public static void f1() throws IOException, ParseException {
		int a = 0;
		if(a == 0) {
			throw new IOException("IOException");
		}else {
			throw new ParseException("解析错误", 1);
		}
	}
	
//	public static void main(String[] args) {
//		//main方法需要捕获多个异常
//		try {
//			f1();
//		} catch (IOException e) {
//			e.printStackTrace();
//		} catch (ParseException e) {
//			e.printStackTrace();
//		}
//	}
	
	public static void main(String[] args) {
		//main方法可以捕获父类异常
		try {
			f1();
		}catch(Exception e){
			e.printStackTrace();
		}
	}	
}

6.练习

1.写一个TestException类,在main方法中接受两个命令行参数,将他们转换成整数,并用第二个数除以第一个数,打印结果。测试一下情况,某个参数不是数字,第一个参数为0.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年之伴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值