Java 异常处理
异常处理是java中很重要的部分,我们平时写代码其实有很多情况考虑不到,或者我考虑到这一行代码有可能会报错我就要想如果报错了我怎么去处理他能让他正常的返回信息给我。程序一旦发生了异常,就会直接在异常代码地方直接退出程序,不再往后执行了。
异常通常分为两类:运行时异常(RuntimeException)和非运行时异常,运行时异常指在写代码时,开发工具(eclips、idea、sts等)不会提示你必须在这一行加异常处理,但是在运行是有可能会抛出异常(一般习惯把程序报错叫做抛异常、抛出异常、报异常),非运行时异常是指我们在写代码时开发工具就会在这一行报错,提示你必须在该处加异常处理机制,不然不给你编译通过。
1、运行时异常
先举一个java中最最最常见没有之一的异常场景:空指针异常,空指针异常是指一个对象在声明的时候没有实例化(new),直接调用其方法所报的异常。
public class Test {
public static void main(String[] args) {
String s = null;
Test test = new Test();
//其实这里应该判断s是否为null,但是我没判断
test.printLength(s);
}
/**
* 打印符串长度
*/
public void printLength(String s) {
System.out.println(s.length());
}
}
按照开发正常做法,我们应该是在调用printLength()之前就应该对s判断是否为null,因为不是所有开发人员都能考虑到调这个方法会先判断的,所以我们也可以在printLength()中用两种方法处理:
- 1、判断s是否为null,如果是的话就打印-1。
- 2、用异常处理。
代码如下:
public class Test {
public static void main(String[] args) {
String s = null;
Test test = new Test();
//其实这里应该判断s是否为null,但是我没判断
test.printLength(s);
}
/**
* 打印符串长度
*/
public void printLength(String s) {
try {
System.out.println(s.length());
}
catch (NullPointerException e) {
System.out.println(-1); //这是我们想要的异常返回值
//下面的代码纯粹是为了告诉你e里面有以下东西可以查看
System.out.println(e); //打印e
System.out.println(e.getMessage()); //打印e.getMessage()
e.printStackTrace(); //打印完成的异常堆栈信息
}
System.out.println("成功执行结束!");
}
}
上面的代码可以看出,异常处理一般分为两个部分(其实还有一个finally关键字在之后的章节里介绍),try-catch,try中写我们认为会报错的代码,catch中写如果报错了需要怎么处理的代码。catch后面括号里面的NullPointerException表示我们要处理的是try中的空指针异常,如果try中多加了一段会触发其它类型异常的代码,我们就需要追加catch代码块。如下代码:
public class Test {
public static void main(String[] args) {
String s = "abc123";
try {
System.out.println(s.length());
int i = 0 / 0; //这个地方会报错,因为除数不能为0
System.out.println("try块结束");
}
catch (NullPointerException e) {
System.out.println("提示:空指针异常!");
}
catch (ArithmeticException e) {
e.printStackTrace();
System.out.println("提示:除数不能为0");
}
System.out.println("程序执行完成");
}
}
上面的代码中,我们事先知道了这个除法会报ArithmeticException,所以我在空指针异常下面追加了一个ArithmeticException代码块的处理,当try中的代码走到int i = 0 / 0
时,直接会出错,程序会查找catch中的异常类型,从上到下先查到了NullPointerException,发现这个异常符合抛出的这个异常,跳过,然后继续往下查找到了ArithmeticException,发现这个异常类型符合抛出的这个异常,就进到ArithmeticException的catch代码块中执行代码了。当catch中的代码执行完,程序会继续往下走,打印“程序执行完成”,而不会走try中的打印“try块结束”。如果try中的代码抛出了异常,我的catch块中并没有对应的处理类型,那就相当于没法处理这个异常程序直接报错中断,代码如下:
public class Test {
public static void main(String[] args) {
String s = null;
try {
System.out.println(s.length());
System.out.println("try块结束");
}
//这个是处理除数不能为0异常,并不能处理上面的空指针异常,程序找不到相应的处理,直接报错停止
catch (ArithmeticException e) {
System.out.println("提示:空指针异常!");
}
System.out.println("程序执行完成");
}
}
假如说上面的我并不知道会报空指针异常和除数不能为0异常,但是我又害怕他报错,我们还有另外的方法解决这个问题,这个方法适用于所有异常,代码如下:
public class Test {
public static void main(String[] args) {
String s = "123";
try {
System.out.println(s.length());
int i = 0 / 0;
System.out.println("try块结束");
}
//我Exception是所有异常的父类,管你是什么类型的异常我都能处理!
catch (Exception e) {
System.out.println("程序出现异常,请联系管理员!");
e.printStackTrace(); //打印堆栈信息
System.out.println(e.getMessage()); //打印异常信息
}
System.out.println("程序执行完成");
}
}
2、非运行时异常
先举一个例子
package hello;
/**
*
* @author wendy
*/
public class DataType {
public static void main(String[] args){
System.out.println("start");
Thread.sleep(2000L);
System.out.println("end");
}
}
这段程序的本意是暂停两秒,但是我在写程序的时候eclips提示我这里有个错误,我必须改正。得到两个自动修正的提示,第一行意思是异常不处理直接向外抛出,第二行意思是使用try-catch块来解决这个异常,其实用那种方式都一样,我们先点击第二行这种方式处理,得到以下代码:
package hello;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author wendy
*/
public class DataType {
public static void main(String[] args){
System.out.println("start");
try {
Thread.sleep(2000L);
} catch (InterruptedException ex) {
Logger.getLogger(DataType.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("end");
}
}
更多示例代码地址:Day14