概述
异常概述
异常就是Java程序在运行过程中出现的错误。
Java中的异常类都继承自java.lang.Throwable。
- Error类称为错误类,它表示Java运行时产生的系统内部错误或资源耗尽的错误,是比较严重的,仅靠程序本身是不能恢复执行的。
- Exception类称为异常类,它表示程序本身可以处理的错误,在开发Java程序中进行的异常处理,都是针对Exception类及其子类。在Exception类的众多子类中有一个特殊的RuntimeException类,该类及其子类用于表示运行时异常,除了此类,Exception类下所有其他的子类都用于表示编译时异常。
JVM默认处理异常的方式:
main函数遇到问题时,有两种处理方式:自己将该问题处理,然后继续运行。自己没有针对的处理方式,只有交到调用main的JVM来处理。JVM有一个默认的异常处理机制,就将该异常处理,并将该异常的名称,异常信息,异常出现的位置打印在了控制台上,同时将程序停止运行。
package com.first;
public class HelloWorld {
public static void main(String[] args) {
int result = 0;
result = 4 / 0;
System.out.println(result);
}
}
控制台显示的内容为
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.first.HelloWorld.main(HelloWorld.java:8)
Throwable的常见方法
- getMessage():获取异常信息,返回字符串
- toString():获取异常类名和异常信息,返回字符串
- printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void
这些方法用于获取异常信息。由于Error和Exception继承自Throwable类,所以它们都拥有这些方法。
try…catch
由于发生了异常,程序立即终止,无法继续向下执行。为了解决这样的问题,Java中提供了一种对异常进行处理的方式—异常捕获。
try:用来检测异常。
catch:用来捕获异常。
try{
//程序代码块
}catch(ExceptionType(Exception类及其子类) e){
//对ExceptionType的处理
}
在try代码中编写可能发生异常的Java语句,catch代码块中编写针对异常进行处理的代码。当try代码块中发生了异常,系统会将这个异常的信息封装成一个异常对象,并将这个对象传递给catch代码块。catch代码块需要一个参数指明它所能够接受的异常类型,这个参数必须是Exception类或其子类。
package com.first;
public class HelloWorld {
public static void main(String[] args) {
int result = 0;
try {
result = 4 / 0;
System.out.println("-----");
} catch (Exception e) {
//Exception e=new ArithmeticException();
System.out.println("进入到catch中");
System.out.println(e.getMessage());
System.out.println(e.toString());
e.printStackTrace();
}
System.out.println(result);
}
}
控制台的内容为
进入到catch中
/ by zero
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero
at com.first.HelloWorld.main(HelloWorld.java:9)
0
在try代码块中发生被0除异常,程序会转而执行catch的代码。catch代码块对异常处理完毕后,程序仍会向下执行,而不会异常终止。
需要注意的是,在try代码块中,发生异常语句后面的代码是不会被执行的。本例中第10行代码的打印语句就没有执行。并且如果try中没有发生异常,不会走catch代码块。
try…跟多个catch
package com.first;
public class HelloWorld {
public static void main(String[] args) {
int a = 10;
int b = 0;
int[] arr = { 11, 22, 33, 44 };
try {
System.out.println(a / b);
//除0异常
System.out.println(arr[10]);
//索引越界异常
arr = null;
System.out.println(arr[0]);
//空指针异常
} catch (ArithmeticException e) {
//ArithmeticException e=new ArithmeticException();
System.out.println("除数不能为零");
} catch (ArrayIndexOutOfBoundsException e) {
//ArrayIndexOutOfBoundsException e=new ArrayIndexOutOfBoundsException();
System.out.println("索引越界了");
} catch (Exception e) {
//Exception e=new NullPointerException();
System.out.println("出错了");
}
System.out.println("over");
}
}
运行结果为
除数不能为零
over
第12行代码出错之后,第一个catch就会执行,后面的catch不会执行。
如果把13行代码注释掉,会执行第二个catch。
如果把第12,13行代码注释掉,会执行最后一个catch,Exception可以接收所有异常。多态的应用
JDK7有个新特性,可以一次catch多种异常,但好像也没什么卵用。
try {
System.out.println(a / b);
//除0异常
System.out.println(arr[10]);
//索引越界异常
arr = null;
System.out.println(arr[0]);
//空指针异常
} catch (ArithmeticException|ArrayIndexOutOfBoundsException e) {
//ArithmeticException e=new ArithmeticException();
System.out.println("除数不能为0或索引越界异常");
} catch (Exception e) {
//Exception e=new NullPointerException();
System.out.println("出错了");
}
throws关键字
如果调用自己的方法,应该很清楚该方法可能会发生异常。但如果去调用一个别人写的方法时,无法判断是否会有异常。针对这种情况,Java中允许在方法的后面使用throws关键字对外声明该方法可能发生的异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过。
修饰符 返回值类型 方法名([参数1,参数2···]) throws ExceptionType1[,ExceptionType2···]{
}
throws关键字需要写在方法声明的后面,throws后面需要声明方法中发生异常的类型,通常将这种做法称为方法声明抛出一个异常。
package com.first;
public class HelloWorld {
public static void main(String[] args) {
int result=divide(4,2);
System.out.println(result);
}
private static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
}
其中第7行代码int result=divide(4,2);
,调用divide()方法时传入的第二个参数为2,程序在运行时不会发生被0除的异常,但是由于定义divide()方法时声明抛出了异常,调用者在调用divide()方法时就必须进行处理,否则就会发生编译错误。
package com.first;
public class HelloWorld {
public static void main(String[] args) {
try {
int result=divide(4,2);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
private static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
}
这样处理后就不会报错了,运行结果为2
当在调用divide()方法时,如果不知道如何处理声明抛出的异常,也可以使用throws关键字继续将异常抛出,,这样程序也能编译通过,但需要注意的是,程序一旦发生异常,如果没有被处理,程序就会被非正常终止。
编译时异常和运行时异常
在Java中,Exception类中除了RuntimeException类及其子类都是编译时异常。编译时异常的特点是Java编译期会对其进行检查,如果出现异常就必须对异常进行处理,否则程序无法通过编译。用try…catch语句进行捕获或用throws关键字声明抛出异常,调用者对其处理。
RuntimeException类及其子类都是运行时异常。运行时异常的特点是Java编译器不会对其进行检查,也就是说,当程序中出现这类异常时,即使没有处理,程序也能编译通过。
FileInputStream fis=new FileInputStream("test.txt");
这句话就会发生编译时异常,必须要对其进行处理。因为到时候可能找不到这个文件。
自定义异常
为什么需要自定义异常?
方便查找错误。如果报的异常都显示为Exception,我哪儿知道是啥错误。
现在自定义一个异常,如果被除数为负数,就抛出异常。
package com.first;
public class HelloWorld {
public static void main(String[] args) {
try {
int result=divide(4,-2);
System.out.println(result);
} catch (DivideByMinusException e) {
e.printStackTrace();
}
}
public static int divide(int x,int y)throws DivideByMinusException{
if (y<0) {
throw new DivideByMinusException("被除数是负数");
}
return x/y;
}
}
class DivideByMinusException extends Exception{
public DivideByMinusException() {
super();
}
public DivideByMinusException(String message) {
super(message);
}
}
运行结果为
com.first.DivideByMinusException: 被除数是负数
at com.first.HelloWorld.divide(HelloWorld.java:18)
at com.first.HelloWorld.main(HelloWorld.java:7)
throw关键字用于在方法中声明抛出异常的实例对象,在一个方法内使用throw关键字抛出异常对象时,需要使用try…catch语句对抛出的异常进行处理,或者在方法上使用throws关键字声明抛出异常,由该方法的调用者负责处理。
finally关键字
有时候我们希望有些语句无论程序是否发生异常都要执行,这时就可以在try···catch语句后,加一个finally代码块。
public class HelloWorld {
public static void main(String[] args) {
try {
int result=divide(4,0);
System.out.println(result);
} catch (Exception e) {
System.out.println("捕获的异常信息为"+e.getMessage());
return;
}finally{
System.out.println("进入finally代码块");
}
System.out.println("程序继续向下执行···");
}
private static int divide(int x, int y) {
int result=x/y;
return result;
}
}
运行结果为
捕获的异常信息为/ by zero
进入finally代码块
在catch代码块中增加了一个return语句,用于结束当前方法,此时程序第14行代码就不会执行了,而finally中的代码仍会执行,并不会被return语句所影响,也就是说无论程序是发生异常还是使用return语句结束,finally中的语句都会执行,在程序设计时,经常会在try···catch后使用finally代码块来完成必须做的事情,例如释放系统资源。
需要注意的是,finally中的代码有一种情况下是不会执行的,那就是在try···catch中执行了System.exit(0)语句。System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了。
一般finally用于释放资源,在IO流操作和数据库操作中会经常用到。
总结
加try,catch并不是为了解决bug问题,如果你在调试阶段,不加try,反而更容易找到bug在哪里,编译器就会自动断点在出问题的代码行上,省了你自己翻日志还找不到具体的原因。
而如果真正运行,很多情况都会导致底层抛出异常,这些一般都是IO操作引起的,比如写文件失败,连接数据库失败,连接以太网失败,以太网读取数据超时。所有IO操作,都依赖于外部设备,跟你自己的代码关系不大(除非有严重BUG),在通信之前,没法预测本次通信到底能不能通的上。类似这种问题,就应该通过try捕获异常,然后程序自动进行重试,而不是遇到啥P大的问题都给用户弹出个对话框,用户看不懂,也不知道该如何解决,这种异常写进文件也没用.因为是很正常的现象,而不是什么bug
能够预知到错误发生的类型,但是无法预知到什么时候会出现问题,所以需要加try,在catch里代码解决能预测的类型,当然最后无法预知的类型也要捕获,这部分可能就需要通过弹出错误信息,写日志,事后来补救了。
最后
以上就是任性毛豆为你收集整理的Java-异常异常概述try…catchthrows关键字编译时异常和运行时异常自定义异常finally关键字总结的全部内容,希望文章能够帮你解决Java-异常异常概述try…catchthrows关键字编译时异常和运行时异常自定义异常finally关键字总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复