为什么我们需要异常机制呢?
不管什么程序,只要是人写出来的,就有出错的可能,比如内存不够、文件找不到、数组下标越界等等。如果这些错误不能及时处理,可能会导致程序无法正常工作,甚至终止运行,给公司带来损失。所以,处理好程序产生的错误,既能够避免程序崩溃,也方便后续维护时发现问题。发现错误的理想时机是在编译阶段,也就是在你运行程序之前;但是,我们并不能保证在运行程序之前就找出所有的错误,所以我们需要一种可以在运行期间一种机制,使该错误源可以将某些信息传递给某个接收者,让其知道如何处理这个问题。针对刚才所说的那些问题,Java 给出了高效简洁而且成熟的异常处理机制。
什么是异常,单就字面意思来讲,异常就是不是按照我想的方向去走的,让我感到意外的事情;当存在一件感到意外的事情时,将其从当前环境中抛出,这样就把信息传递到“更大的环境中了”,我们叫做抛出异常。
例如:
if(t == null)
throw new NullPointerException();
throw与throws有什么区别:throw就是上面所说的抛出异常,而throws更像一种声明,当其他的类或者子类调用这个方法时给予提醒,调用这个方法有可能造成以上类型的异常,要注意异常的捕获和处理。
异常捕获:异常在抛出过后处于待处理阶段,如何去处理这些异常成为了重中之重。在这里我们采用try-catch结构;如果在方法内部抛出了异常(或者在方法内部调用的其他方法抛出了异常),这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内设置一个特殊的块来捕获异常。因为在这个块里“尝试”各种(可能产生异常的)方法调用,所以称为 try 块。当然,抛出的异常必须在某处得到处理。这个“地点”就是异常处理程序,而且针对每个要捕获的异常,得准备相应的处理程序。异常处理程序紧跟在 try 块之后,以关键字 catch 表示。在try块中可能会由不同的方法产生相同的异常,在catch中仅对每种异常给出相应的解决方法
try {
} catch(Type1 id1) {
} catch(Type2 id2) {
} catch(Type3 id3) {
}
finally子句进行清理:当在进行一些内存回收和垃圾清理时我们希望无论发生什么事情最终这段程序代码都被执行,为了达到这一效果我们在try-catch子句的后面加上finally子句实现这一目的
try {
//一段程序代码
} catch(A a1) {
} catch(B b1) {
} catch(C c1) {
} finally {
//无论如何这段代码都会被执行
}
缺陷:容易造成异常丢失。
自定义异常类要自定义异常类必须继承已经存在的异常类,这个异常类最好是由相近意思的异常类继承而来的。
class SimpleException extends Exception {}
public class InheritingExceptions {
public void f() throws SimpleException {
System.out.println(
"从f抛出SimpleException异常");
throw new SimpleException();
}
public static void main(String[] args) {
InheritingExceptions sed =
new InheritingExceptions();
try {
sed.f();
} catch(SimpleException e) {
System.out.println("这是一个异常");
}
}
}
从f抛出SimpleException异常
这是一个异常
多重捕获: 在Java7之后,允许程序通过
try {
} catch(Except1 | Except2 | Except3 | Except4 e) {
}
的方式进行多重捕获,这种方式有利于代码的书写。
Java当中的异常被当作对象来处理,所有异常类的父类都是java.lang包下的Throwable类。异常又被分成两大种,一种是错误error,一种是异常Excption。
Error代表了Java自身那些不能被工程师处理的错误,比如内存耗尽,系统崩溃,这是一种人力所无法预见和掌握的因素。
Excption表示程序运行时可能发生的非正常事件,可以被捕获,抛出和处理,这是Java异常处理的核心。
Excption类又分为运行时异常 (RuntimeExcption)和非运行时异常,亦可称为非检查时异常(Unchecked Excption)和检查异常(Checked Excption)
非检查异常(Unchecked Exception): 包括 Error 和 RuntimeException 及其它们的子类,Java 在编译源代码时,不会提示和发现这样的异常。所以这种异常的出现,几乎可以肯定就是代码写的有问题。
检查异常(Checked Exception): 除了 Error 和 RuntimeException 之外所有的其它异常。Java 强制要求工程师处理这类异常(也就是用特定的语法 try…catch…finally 捕获并处理这类异常)。
异常的实验:
(1)创建一个 Java 数组,然后访问不存在的数组数据,看看会抛出什么异常。
答:会出现ArrayIndexOfBoundsExcption数组索引越界异常
(2)执行代码 System.out.println(1 / 0),看看会抛出什么异常。
答:会出现ArithmeticException算术运算异常。
(3) 结合 Java 对象的知识,依据图 2,创建一个 Human 类,增加一个性别属性,并且在性别的 setter 方法里如果性别不为「男」或「女」抛出图 2 的 GenderException 自定义异常(定义全部的四种构造器,并且以这四种方式抛出异常)。
答:
public class GenderException extends Exception{
public GenderException() {
super();
}
public GenderException(String message) {
super(message);
}
public GenderException(String message, Throwable cause) {
super(message, cause);
}
public GenderException(Throwable cause) {
super(cause);
}
}
public class Human {
String gender;
public String getGender() {
return gender;
}
public void setGender(String gender) throws GenderException {
if (gender.equals("男") || gender.equals("女")) {
this.gender = gender;
} else {
try {
throw new GenderException("这是一个性别错误");
}catch (GenderException e){
e.printStackTrace();
}
}
}
}
public class Example {
public static void main(String[] args) {
Human human = new Human();
try {
human.setGender("a");
}catch (Exception e){
e.printStackTrace();
}
}
}
感谢您的阅读,如果本篇文章对您有帮助,欢迎点赞,关注,您的阅读是我莫大的鼓励!