Java 之 Java 异常处理

Throwable

Throwable(异常最顶端的类)
	Error(服务器奔溃,数据库奔溃)
	Exception(异常类)
		RuntimeException(运行时异常,编写程序时,程序员犯的错)

出现异常解决思路:
1.出现异常去找上级解决
2.找上级解决相当于找任务的调用者,main 的调用者 JVM 处理
3.JVM 默认的处理方式:打印异常类,错误信息和错误发生的位置,直接停止程序
常见的异常
1.空指针异常 NullPointerException
2.角标越界异常 ArrayIndexOutOfBoundsException
3.算术异常 ArithmeticException

写出这些异常:
1.空指针异常
int[] array = new int[3];
System.out.println(array[4]);

2.角标越界异常
int[] array = new int[3];
array = null;
System.out.println(array[0]);

3.算数异常
System.out.println(10 / 0);

try…catch…finally

try 指测试异常代码
catch 指捕获异常信息
finally 指异常结束后要做的事

try.....catch 捕获异常的流程
1.函数中某句代码可能会发生异常
2.发生异常就会产生对应的异常对象
3.这个异常对象返回给调用者
  情况1:没有对异常进行处理,这时就会把异常交给上级 JVM 去处理
  JVM 就会使用默认的处理机制:打印异常类,错误信息和错误发生的位置,直接停止程序
  情况2:调用者进行了异常处理(try..catch)
  这时,返回的异常对象,会和 catch 进行匹配
  匹配成功,则执行 catch 中的语句,程序继续运行
public class Demo {
	public static void main(String[] args) {
		TestException testException = new TestException();
		try {
			// 可能发生异常的代码
			int num = testException.fun(10, 0);
			System.out.println(num);
		} catch (Exception e) {
			// 捕获异常
			// (ArithmeticException e) ArithmeticException e = new ArithmeticException("/ by zero");
			// (Exception e) Exception e = new ArithmeticException("/ by zero");
			//()中要放捕获的是什么异常
			System.out.println("/ by zero");
		}
	}
}
class TestException{
	// 除法,返回两个数的商
	public int fun(int a, int b) {
		// 这句产生异常?
		// 发生异常一定会产生一个对应异常对象
		// new ArithmeticException("/ by zero");
		return a / b;
	}
}

多 catch 处理异常

int[] array = new int[3];
try{
	// 报越界异常,产生越界异常的对象
	System.out.println(array[4]);
	array = null;
	System.out.println(array[0]);
	System.out.println(10/0);
} catch (NullPointerException e) {
	System.out.println("空指针异常");
} catch (ArrayIndexOutOfBoundsException e) {
	// 匹配 catch 的时候,有一个被匹配上是,其他 catch 就不会继续匹配下去
	 System.out.println("角标越界异常");
} catch (ArithmeticException e) {
	System.out.println("/ by zero");
} catch (Exception e) {
	// 注意:如果 catch 中要写 Exception 一定要放在最下面
	System.out.println("写错了");
}
System.out.println("---");

finally

 出现异常与否,不会影响到 finally 的执行
 finally 一定会执行
 finally 的作用:一般会用来关闭资源(关闭流/数据库等等)

注意:final finally finalize 的区别?
final finally finalize 无任何联系,没有对比性
final 类不能被继承,方法不能被重新,变量定义为常量
finally 异常处理的时候使用,不可单独写,可以和 try 直接连用
finalize()是一个方法,做垃圾回收的时候使用,系统需要时,自己进行调用
try {
	System.out.println(10 / 0);
	// 即使直接 return 方法, finally 也会执行
	// 例外:直接关闭 JVM 虚拟机关了就不执行了  System.exit(0);
	return;
} catch (Exception e) {
	System.out.println("/ by zero");
} finally {
	System.out.println("我还有一句话,不知当讲不当讲!");
}
System.out.println("--------");
安卓开发
客户端开发   直接使用 Exception e 来接收异常

JavaEE开发
服务器开发   一般会把异常记录下来,写成错误日志,回头查看
如果不记录,相当于把这个错误遗漏过去
int num = 10;
try {
	num = 20;
	System.out.println(7 / 0);
	return num;
} catch (Exception e) {
	// 捕获异常
	num = 30;
	// 建立一个返回路径,相当于有一个箱子
	// 箱子中保存的是,要返回的值
	// 不会马上 return,会看一下,有没有 finally
	// 有 finally 就执行,但是不会更改已经在返回路径中的值
	// 等 finally 执行完了.再完全 return
	return num;
} finally {
	num = 40;
	// finally 只写关闭资源,写 return 没有
	// 在 finally 中放 return ,会导致之前的返回值全部覆盖掉
	// return num;
}
运行时异常和编译时异常

运行时异常(程序员犯的错)
编译时异常(为了可能发生的错误做的提前准备)
public static void main(String[] args) throws FileNotFoundException {
	/*
	 * 编译时异常
	 * 
	 * 准备读取该路径下的文件
	 * 系统不知道这个路径中有没有这个文件
	 * 需要提前询问一下,如果没有这个路径下的文件
	 * 编译时异常,是系统强制程序员需要处理的
	 * 处理方式1:添加 try...catch (自行进行处理)
	 * FileInputStream inputStream = new FileInputStream("wl.txt");
	 * 处理方式2:把异常抛给上级去处理(和自己没关系了)
	 * 把问题 抛给 main 函数,在 main 函数声明上添加 throws 要抛出的异常类名
	 */
	/*
	 * 处理方式1:
	 * try {
	 * 		FileInputStream inputStream = new FileInputStream("wl.txt");
	 * } catch (Exception e) {
	 * 		System.out.println("路径下无此文件!");
	 * }
	 */
	/*
	 * 处理方式2:
	 * public static void main(String[] args) throws FileNotFoundException(将异常抛给 main 函数)
	 */
//		FileInputStream inputStream = new FileInputStream("wl.txt");
}

Throwable

public static void main(String[] args) {
Exception exception = new Exception("这里可以写错误信息");
	// 获取错误信息
//		String message = exception.getMessage();
//		System.out.println(message);
	
	// toString 方法
//		System.out.println(exception);
	
	// 打印错误信息,错误位置,异常类的类名
	exception.printStackTrace();
}

自定义异常

public class Demo {
	public static void main(String[] args){
		Persons person = new Persons();
		person.setName("甲");
		try {
			person.setAge(130);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(person);
	}
}
// 自定义异常类
// 重点:类名要见名知意,并且跟系统学习
class AgeOutOfBoundsException extends Exception{
	/**
	 * 序列化时使用的 id
	 */
	private static final long serialVersionUID = 1L;

	// 写无参和有参的构造方法
	public AgeOutOfBoundsException() {
		super();
	}

	public AgeOutOfBoundsException(String message) {
		super(message);
	}
	
}
class Persons {
	private String name;
	private Integer age;
	public Persons() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Persons(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	// throws 关键词在方法的声明上标识这个方法可能会抛出异常 
	// 谁调用这个方法,这个异常就抛给谁
	public void setAge(Integer age) throws Exception {
		// 需要在这个范围内,才给 age 赋值
		if (age <= 120 && age >=0) {
			this.age = age;
		} else {
			throw new AgeOutOfBoundsException("超出定义范围");
		}
	}
	@Override
	public String toString() {
		return "[姓名:" + name + ", 年龄:" + age + "]";
	}
	
}
例题:
// 无限输入整数 存放到集合中 打印 输入quit停止
// 希望在输入     字符串的时候 让程序也能继续运行
public class Demo {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		// 创建集合
		ArrayList<Integer> arrayList = new ArrayList<>();
		int index = 1;
		while (true) {
			System.out.println("请输入第"+ index +"整数(输入 quit 时结束输入):");
			// 接收输入数据
			String string = scanner.nextLine();
			if (string.equals("quit")) {
				// 停止循环
				break;
			}
			try {
				// 字符串转数字
				int parseInt = Integer.parseInt(string);
				// 添加到数组中
				arrayList.add(parseInt);
				index++;
			} catch (Exception e) {
				System.out.println("请输入第"+ index +"整数(输入 quit 时结束输入):");
				// 接收输入数据
				string = scanner.nextLine();
			}
		}
		System.out.println(arrayList);
		// 循环结束打印一下
		scanner.close();
	}
}
// 
class AllInteger extends Exception{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
}

抛出异常(throw)

编译异常:系统会强制你去处理,try 或者抛
运行时异常(RuntimeException)(除了运行时异常其他都是编译时异常)
1.抛出运行时异常,方法的声明上,可以不用 throws 来标识
2.可以不对运行时异常进行处理
  不处理直接停止程序
  处理程序可以继续执行

编写时,如果在方法中抛出运行时异常,说明如果发生了该异常,就需要停掉程序,让程序再执行下去没有意义!
例如:
输入两个数字进行运算,先通过 string 接受,当输入的不可以转换成 Integer 类型时,就会报异常
测试编译异常
try {
	Test.test();
} catch (Exception e) {
	e.printStackTrace();
}
class Test{
	// 抛出编译异常
	public static void test() throws Exception{
		throw new Exception();
	}
}
测试运行时异常
try {
	Test.test();
} catch (Exception e) {
// 抛出编译异常
class Test{
	// 抛出运行时异常
	public void test2() {
		throw new RuntimeException();
	}
}
// 计算圆的面积
double area = Test.getArea(-1);
System.out.println(area);

class Test{
	// 计算圆面积
	public static double getArea(double r) {
		// 如果半径小于等于0,接下去的运算将没有意义
		// 这时可以抛出运行时异常,来停止程序,修改代码
		if (r < 0) {
			throw new RuntimeException("半径输入有误!");
		}
		return r * r * Math.PI;
	}
}

继承中的方法重写异常

父类抛出编译异常,子类可以不抛出异常
class Father{
	 public void test() throws Exception{
		 
	 }
	 
}
class Son extends Father{
	@Override
	public void test() {
		
	}
}
父类抛出编译异常,子类可以抛出异常
class Father{
	 public void test() throws Exception{
		 
	 }
	 
}
class Son extends Father{
	@Override
	public void test() throws Exception{
		
	}
}
父类没有抛出编译异常,子类不可以抛出编译异常!
当子类重写父类方法时,调用了一个有异常的方法,只能用 try...catch 处理异常,不能抛出异常
class Father{
	 public void test(){
		 
	 }
	 
}
class Son extends Father{
	@Override
	public void test(){
		try {
			method();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	// 带异常的方法
	public void method() throws Exception{
	 
	}
}
例题:
/*
 * 获取数字的工具类
 * 要求:从键盘输入 输入的是字符串要处理异常重新输入
 * 
 * 封装一个有两个数的对象类
 * 要求:类中有两个int数字 作为成员变量
 * 
 * 封装自定义异常类
 * 要求:类名表示除法除数不能为0 
 * 
 * 封装运算类
 * 1.获取 两个数的对象
 * 2.获取 要做的运算法则 加法或者除法 
 *   输入数字1是加法 2是除法(输入错误 要重新输入)
 * 3.加法方法
 * 4.除法方法(要求捕获异常 并抛出自定义异常)
 * 5.根据运算法则 执行运算 并返回运算结果
 *   除数如果是0 要重新输入数字
 *   
 * 测试类:
 * 对以上方法进行测试
 */
 
/*
 * 封装一个有两个数的对象类
 * 要求:类中有两个int数字 作为成员变量
 */
public class MyNum {
	private int num1;
	private int num2;
	public MyNum() {
		super();
		// TODO Auto-generated constructor stub
	}
	public MyNum(int num1, int num2) {
		super();
		this.num1 = num1;
		this.num2 = num2;
	}
	public int getNum1() {
		return num1;
	}
	public void setNum1(int num1) {
		this.num1 = num1;
	}
	public int getNum2() {
		return num2;
	}
	public void setNum2(int num2) {
		this.num2 = num2;
	}
	@Override
	public String toString() {
		return "[num1=" + num1 + ", num2=" + num2 + "]";
	}
}
/*
 * 获取数字的工具类
 * 要求:从键盘输入 输入的是字符串要处理异常重新输入
 */
@SuppressWarnings("resource")
public class IntTools {
	// 私有化构造方法
	private IntTools() {
		
	}
	// 递归
	public static int getIntNum() {
		System.out.println("请输入一个数字");
		Scanner scanner = new Scanner(System.in);
		String string = scanner.nextLine();
		try {
			// 字符串转数字
			int num = Integer.parseInt(string);
			return num;
		} catch (Exception e) {
			// 再次调用本方法,进行数字的输入
			return getIntNum();
		}
	}
	// 循环
	public static int getNum() {
		System.out.println("请输入一个数字");
		Scanner scanner = new Scanner(System.in);
		String string = null;
		while (true) {
			string = scanner.nextLine();
			try {
				// 字符串转数字
				int num = Integer.parseInt(string);
				return num;
			} catch (Exception e) {
				System.out.println("请输入一个整数!");
			}
		}
	}
}
public class IsNotZeroException extends Exception{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	// 构造
	public IsNotZeroException() {
		super();
	}
	public IsNotZeroException(String message) {
		super(message);
	}
	
}
/*
 * 封装运算类
 * 1.获取 两个数的对象
 * 2.获取 要做的运算法则 加法或者除法 
 *   输入数字1是加法 2是除法(输入错误 要重新输入)
 * 3.加法方法
 * 4.除法方法(要求捕获异常 并抛出自定义异常)
 * 5.根据运算法则 执行运算 并返回运算结果
 *   除数如果是0 要重新输入数字
 */
public class Operation {
	// 获取两个数的对象
	public static MyNum getMyNum() {
		// 构建这个 MyNum 对象需要两个数
		int num1 = IntTools.getIntNum();
		int num2 = IntTools.getIntNum();
		MyNum myNum = new MyNum(num1, num2);
		return myNum;
	}
	/*
	 * 获取 要做的运算法则 加法或者除法 
	 * 输入数字1是加法 
	 * 2是除法(输入错误 要重新输入)
	 */
	public static String getChooseMethod() {
		System.out.println("输入数字1是加法 2是除法(输入错误 要重新输入)");
		int num = IntTools.getIntNum();
		// 判断数字返回要做的运算
		if (num == 1) {
			return "+";
		} else if (num == 2) {
			return "/";
		} else {
			return getChooseMethod();
		}
	}
	// 加法
	public static int sum(MyNum myNum) {
		return myNum.getNum1() + myNum.getNum2();
	}
	// 除法
	// 为什么这里抛出了一个异常,没写返回值不报错?
	public static int division(MyNum myNum) throws IsNotZeroException {
		try {
			return myNum.getNum1() / myNum.getNum2();
		} catch (ArithmeticException e) {
			// 获取到这个异常了,但是不处理
			// 交给方法的调用者去处理
			// 抛出异常,交给调用者去处理
			throw new IsNotZeroException("除数为0!");
		}
	}
	/*
	 * 根据运算法则 执行运算 并返回运算结果
	 * 除数如果是0 要重新输入数字
	 */
	public static int getResultByOperationAndMyNum(String operact, MyNum myNum) {
		// 判断操作符,做相应的运算
		if (operact.equals("+")) {
			return sum(myNum);
		}
		// 除法
		try {
			// 报了异常,除数是0的时候
			// 需要重新输入那两个数
			return division(myNum);
		} catch (IsNotZeroException e) {
			System.out.println(e.getMessage());
			// 重新调用获取两个数对象的方法
			MyNum newNum = getMyNum();
			// 重新调用运算的方法,进行运算
			return getResultByOperationAndMyNum(operact, newNum);
		}
	}
}
/*   
 * 测试类:
 * 对以上方法进行测试
 */
public class Test {
	public static void main(String[] args) {
		operactStart();
	}
	// 封装运算开始的方法
	public static void operactStart() {
		// 获取运算符
		String operact = Operation.getChooseMethod();
		// 获取两个对象
		MyNum myNum = Operation.getMyNum();
		int resultByOperationAndMyNum = Operation.getResultByOperationAndMyNum(operact, myNum);
		System.out.println(resultByOperationAndMyNum);
	}
}


http://blog.csdn.net/huzongnan/article/list

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值