Java 错误与异常及其处理 - Go语言中文社区

Java 错误与异常及其处理


Java中有一个异常处理机制。在我们运行的程序中,出现异常却不去处理的话,整个程序就会终止运行。在面向用户编写程序时更要注意,毕竟墨菲也说了,“ 如果坏事情有可能发生,不管这种可能性多么小,它总会发生,并引起最大可能的损失。”所以我们要在编写程序时就应该及时处理这些引起的异常。

下面是一个大概的流程,主要分为,异常体系和异常处理(补救)。

一、异常体系

    Throwable

      Throwable 是Java中所有错误或异常的超类,只有一个类(或其子类)实例化了 Throwable 类,这个类才能叫做一个 错误 或 异常  ,才能被 Java 虚拟机、Java 语句 throw 抛出、被 try 接收,被 catch 捕获。

      Throwable 有两个子类,分别是 Error (错误)Exception(异常),其中 Exception 可以将他的子类分为两个部分, RuntimeException(运行时错误) 和其他子类。为什么这样分呢?是因为,在Java的异常体制中,将错误及异常分为两个大类,分别是,非检查异常和检查异常。

      非检查异常: Error 全部子类、RuntimeException

      检查异常:Exception 中除 RuntimeException 外的所有子类。

两者有什么区别?

     非检查异常: 通常在编码时,不对非检查异常的处理提出明确的要求。

       非检查异常有 Error 和 RuntimeException 。Error 指 JVM (Java虚拟机)的错误,较常见的是栈溢出、内存不足的错误,像StackOverflowError、OutOfMemoryError 等都是JVM 中的错误。RuntimeException 是运行时错误,例如,NullPointerException(空指针)、IndexOutOfBoundsException(数组越界) 等,是你编码时无法直接发现,而是在编译或运行时发现的异常。

       怎么处理?(捕获、抛出、代码修改、不处理)对于非检查异常,你可以直接在代码中进行处理,例如利用 throw 抛出、利用 try catch 直接进行处理,但是由于这种错误非常多而且难以控制,如果你打算通过上述方法直接进行处理的话,代码量将会非常的巨大、可读性将会非常差。因此,一般建议在编码时考虑周全、严谨。亦或者,你还可以完全不管。

       例如,在处理数组越界 IndexOutOfBoundsException 异常时,你自然可以通过 try catch 来捕获、处理异常。但是其实你只需要在进行相关数组操作前,判断 index 是否在数组范围内即可。如下:

ArrayList<Point> list = new ArrayList<Point>();
int index = 5;
// 直接利用 try catch 捕获、处理
try {
	list.get(index);
} catch (IndexOutOfBoundsException e) {
	e.printStackTrace();
}
		
// 判断
if (index >= 0 && index < list.size())
	list.get(index);
    

检查异常: 在编码的时候,编译器要求你必须要处理的问题。即你在编码的过程中,编译器就会给出相应的错误信息提示。要求你一定要 解决,否则无法编译通过。

     检查异常是 Exception 类的子类中除 RuntimeException 外的全部子类。例如线程休眠语句 sleep(100); 在你敲好这句代码后,编译器就会提示你一个异常 : InterruptedException .

怎么处理。(抛出、捕获)。你自然可以直接抛出,但是在程序中,抛出的错误始终也是需要解决的,并且,错误一般有其发生错误特定的环境,向外 throw 抛出越多,就越难以根据具体环境进行相关捕获后的处理操作。所以一般建议,直接进行捕获、处理(某些情况下还是需要抛出的)。

二、自定义异常类

     当Java提供的异常类不能满足特定环境下的异常检查时,个人根据具体情况,编写的一个继承 Exception 类的类。

    例如,在银行的存钱系统中,如果你的入账资金是一个负数,那这就是一个错误,但是Java提供的错误、异常类并不会检测出来,因此在这种情况下,你需要自己写一个异常,如下:  

     自定义一个 异常类

public class BankException extends Exception {

	String message;

	public BankException(int m) {
		message = "存入的款项为" + m + ",是一个负数,输入错误。";
	}

	public void printMessage() {  //打印异常信息
		System.out.println(message);
	}
}

       在某一个类中使用,注意,在要抛出异常的方法声明时,用 throws 声明产生的异常

标题

在另外一个操作类中调用 Bank 中的inputMoney 方法的时候一定要进行相应的异常处理,你可以选择抛出或用 try catch 捕获。否则就会报错

public class Operator {

	public static void main(String[] args) {
		Operator operator = new Operator();
		operator.addMoney();
	}
	
	int money = 0;
	
	public void addMoney()  {
		Bank bank = new Bank(money);
		System.out.println("第一笔钱 50元");
		try {
			money = bank.inputMoney(50);
		} catch (BankException e) {
			e.printStackTrace();
		}
		
		System.out.println("第一笔钱操作结束");
		System.out.println("第二笔钱 -50元");
		try {
			money = bank.inputMoney(-50);
		} catch (BankException e) {
			e.printMessage();    //这是我们在自定义异常编写的输出语句
			e.printStackTrace();  //这是Throwable 类定义的异常输出语句
		}
		
		System.out.println("第二笔钱操作结束");
                System.out.println("余额为"+money);
	} 
	
}

输出结果为:

在Java的检查异常类中,类的构建基本都是这样,例如 Thread 类中的 sleep() 方法,源代码如下:

 public static void sleep(long millis, int nanos) throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException("nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

三、异常处理

      1.  对于非检查异常,你最好使得代码更加得严谨,结合Java给出的错误、异常信息,通过打印数据,一步步检查,或者通过断言一步步跟踪。当然,你也可以使用处理异常的关键字,但是这有时会使得代码较长。

      2. 对于检查异常,通过关键字的捕获、处理来解决。有五个关键字,try、 catch 、finall 、throw、throws

       try  catch  配套使用,catch 的作用就是捕获 throw 关键字抛出的异常对象。

(当可能产生的异常种类很多的时候,建议最后catch中的参数类型为 Exception ,避免漏掉某些异常没有捕获)

try{

    //会引起异常的代码

}catch( 某检查异常类 e){
 
    //捕获异常后进行的相关操作

}catch(Exception e){ //这里的参数类型,可以是检查异常共有的父类,也可以是单独不同的具体异常类

    //捕获异常后进行的相关操作

}

      finally 最后输出的语句,即使在 try 和 catch 有 return ,也会在执行完 finally 语句后才去执行 return 语句, finally 语句中不可以有return 语句,try 和 catch 中可以有,但是不建议将return语句放在 try 和 catch 中。

try{
//有可能发生异常的代码
} catch(异常类 变量)
{
// 处理异常的代码,捕获
}
finally{
//一定会被执行的代码
}

   

	public static void main(String[] args) {
		Test test = new Test();
		int m =test.init();
		System.out.println("m = "+m);
	}
	public int init() {
		int m = 0;
		try {
			System.out.println("这里是try");
			m = 5 / 0; // 这里会有一个非检查异常,catch 将其捕获
			return m;
		} catch (Exception e) {
			System.out.println("这里是catch");
			e.printStackTrace(); //打印错误信息
			return -1;
		} finally {
			System.out.println("这里时finally语句");
		}
	
	}

输出为:

throw throws 的使用参照自定义异常类部分。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/www_chinese_com/article/details/84782459
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-20 11:50:41
  • 阅读 ( 309 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢