文章涉及内容来源:黑马程序员自学整理的笔记,网上查阅资料,以及转载名为墨钺的博客大佬,附上博客转载地址:https://www.cnblogs.com/gothic-death/p/9946415.html
在说java异常处理情况之前简单说下:java中异常的定义。
java程序在运行时出现的不正常情况称之为异常。为了防止此类情况发生后及时处理该异常,java将所有可能发生异常的情况用类的形式进行描述和封装。描述不正常情况的类称为异常类。以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题代码相分离,提高了阅读性。其实异常就是java通过面对对象的思想将问题封装成对象,用异常类对其描述,不同的问题用不同的异常类进行具体的描述,如空指针和数组越界等。
问题很多,意味着描述的类也挺多,将其共性进行向上抽取,形成了异常体系,最终问题(不正常情况)就分成了两大类。
该体系的特点就在于Throwable及其所有子类都具有可抛性,且该子类的后缀名都是以其父类命名的,阅读性极强。
Throwable:无论是error还是异常都是问题,只要是问题发生,就应该抛出,让调用者知道并处理。
可抛性到底是什么呢?怎么体现可抛性呢?
其实是通过两个关键字来体现的,throws和throw,凡是可以被这两个关键字所操作的类和对象都具有可抛性。
一般不可处理的:在java中被称作error。特点:是由JVM抛出的严重性问题,这种问题发生一般不针对处理,直接修改程序。
可以处理的:叫做Exception。
其中Exception又被分为两类:编译时异常和运行时异常。
编译时异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。这样的问题都可以针对性的处理。
运行时异常:就是Exception中的RuntimeException和其子类。这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的或者引发了内部状态的改变导致的。这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。
说了这么多,接下来说下自定义异常类所需要注意的事项:
首先说下throw和throws的区别:
1.throws使用在函数上,throw使用在函数内。
2.throws抛出的是异常类,可以抛出多个,中间用逗号进行隔开。throw抛出的是异常对象。
其次说下继承的问题:
自定义异常时,要么继承Exception。要么继承RuntimeException。两者只能选其一。
接下来说下格式要求和注意点:
异常处理的原则:
1、函数内容如果抛出需要检测的异常,那么函数上必须要声明。
否则必须在函数内用trycatch捕捉,否则编译失败。
2、如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。
3、什么时候catch,什么时候throws 呢?
功能内容可以解决,用catch。
解决不了,用throws告诉调用者,由调用者解决 。
4、一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。
内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
紧接着我们来说下java项目中常用的异常处理情况。
1、java.lang.NullPointerException(空指针异常)
发生该情况一般是字符串变量未初始化,数组或数组元素未初始化,类对象未初始化或者是对象不存在等。
解决方案:
1、对字符串变量使用if语句判断是否为空,为空抛出一个异常。
2、数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化, 依然是空的,所以还需要对每个元素都进行初始化。
3、对类进行初始化的检查,若未初始化抛出异常告知调用者。
4、避免去调用可能为null的对象的方法(静态方法除外)。
5、借助一些工具类,比如Apache StringUtils。
2、 java.lang.ClassNotFoundException(指定的类不存在)
这个问题比较容易解决,解决方案:
1、考虑一下类的名称和路径是否正确。
2、缺包,这时只要下载并导入相应的包即可;当我们已经把包导入的时候,又报了这种错误的情况下,就需要开启自己的编辑器去调整设置了;在使用tomcat的时候,先检查lib中是否导入了jar。
3、对类名和包名验证,类名验证代码如下:
package exception; public class test { public static void main(String[] args) { try { Class.forName("exception.Mytest");
}
catch (ClassNotFoundException e) { e.printStackTrace(); }
}
}
解决包名错误时,可以在编译时,加上【 -d . 】这样可以把当前的目录加入到classpath中。
3、 java.lang.NumberFormatException(字符串转换为数字异常)
这个错误就是字符串中出现非数字型字符时,如(123#456)转换为数字时发生异常;除此之外,如果字符串转换为数字时超过了类型的范围(比如string转int和string转double),也会出现这个错误。解决该问题的方法就是在转换之前先对字符串进行检查。
解决方案:以如下代码为例
版权声明:此代码为CSDN博主「morethansea」的原创,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/morethansea/article/details/51456580
package shiyan6; import java.util.*; public class demo1 { //千万别把类名写成 NumberFormatException public static void main(String[] args){ Scanner input = new Scanner(System.in); boolean inputinteger= true; System.out.println("Please input two integer:"); do{ try { //输入的数字或字母等都先当成String类型储存 String number1 = input.nextLine(); String number2 = input.nextLine(); int n1 = Integer.parseInt(number1); int n2 = Integer.parseInt(number2); //不可以可以转化成整数就会产生想要的异常 //显示结果 System.out.println("The sum of the two integer is:"+(n1+n2) ); inputinteger = false;//没错就退出 } catch (NumberFormatException e) { System.out.println("NumberFormatException!Try to input again:please input the integer!"); } }while(inputinteger);//输入不对继续输入 } }
上述代码就对该异常进行了捕捉和处理,并给出了提示信息,当然自己也可以自定义异常类进行对字符串的判断。
4、java.lang.IndexOutOfBoundsException(数组下标越界异常)
这个我们应该特别熟悉,处理方法也较为简单,这里简单说下我自己的思路:
1、定义一个函数判断输入的数字是否大于数组长度,若大于则抛出一个异常并捕获,用printStackTrace()(jvm默认的异常处理机制就是调用异常对象的这个方法)告诉调用者出错的位置和原因。
在这里引用下毕向东老师的源码:
class Demo { public int show(int index)throws ArrayIndexOutOfBoundsException { if(index<0) throw new ArrayIndexOutOfBoundsException("越界啦!!"); int[] arr = new int[3]; return arr[index]; } } class ExceptionDemo5 { public static void main(String[] args) { Demo d = new Demo(); try { int num = d.show(-1); System.out.println("num="+num); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.toString()); // return ; // System.exit(0);//退出jvm。 } finally//通常用于关闭(释放)资源。 { System.out.println("finally"); } System.out.println("over"); } }
2、循环输出数组的内容尽量用数组名.length来代替变量。
5、java.lang.IllegalArgumentException(方法的参数错误)
这个一般是由参数传递类型或少传参导致的,在调用传参方法时,可先对参数类型和个数进行检查,若发现错误可及时告诉调用者,由调用者进行问题的处理。
所以在调用带有参数的方法时,请注意传递的参数或个数是否正确。
6、java.lang.IllegalAccessException(没有访问权限)
当应用程序要调用一个类,但当前的方法即没有对该类的访问权限便会出现这个异常。对程序中用了Package的情况下要注意这个异常。
处理办法:根据异常找到方法,修改方法的访问权限,一般是改为public。
7、java.lang.ArithmeticException(数学运算异常)
除数为0时会报出该错误,解决方法:避免除数为0。这个错误解读为“出现异常的运算条件”,除了除数为0的情况之外,可能还有其他的异常情况,到时具体情况具体分析。这里引用下王建民老师的代码对该异常进行处理。
package test; import javax.swing.*; class AboutException { public static void main(String[] a) { int i=1, j=0, k; try { k = i/j; // Causes division-by-zero exception //throw new Exception("Hello.Exception!"); } catch ( ArithmeticException e) { System.out.println("被0除. "+ e.getMessage()); } catch (Exception e) { if (e instanceof ArithmeticException) System.out.println("被0除"); else { System.out.println(e.getMessage()); } } finally { JOptionPane.showConfirmDialog(null,"OK"); } } }
8、java.lang.ClassCastException(数据类型转换异常)
当试图将对某个对象强制执行向下转型,但该对象又不可转换又不可转换为其子类的实例时将引发该异常,如下列代码。
Object obj = new Integer(0);
String str = obj;
解决方案:
在进行强制类型转换时容易发生该错误,在进行转换前先对类型进行判别,规避错误。
9、javaweb页面异常,你所访问的资源不存在或者不愿被访问(这里只针对自己出现的错误)
出现这种错误的原因一般为JSP文件放在xml目录中或自己的数据库未创建相关表和数据库名称,还有可能数据库密码错误。
解决方案:依次排除这些选项即可。
10、 java.lang.FileNotFoundException(文件未找到异常)
当程序试图打开一个不存在的文件进行读写时将会引发该异常。该异常由FileInputStream,FileOutputStream,RandomAccessFile的构造器声明抛出,即使被操作的文件存在,但是由于某些原因不可访问,比如打开一个只读文件进行写入,这些构造方法仍然会引发异常。
11、 java.lang.EOFException(文件已结束异常)
当程序在输入的过程中遇到文件或流的结尾时,引发异常。因此该异常用于检查是否达到文件或流的结尾
12、java.lang.InstantiationException(实例化异常)
当试图通过Class的newInstance()方法创建某个类的实例,但程序无法通过该构造器来创建该对象时引发。Class对象表示一个抽象类,接口,数组类,基本类型 。该Class表示的类没有对应的构造器。
13、java.lang.InterruptedException(被中止异常)
当某个线程处于长时间的等待、休眠或其他暂停状态,而此时其他的线程通过Thread的interrupt方法终止该线程时抛出该异常。
14、java.lang.CloneNotSupportedException (不支持克隆异常)
当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常。
15、java.lang.OutOfMemoryException (内存不足错误)
当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。
16、java.lang.NoClassDefFoundException (未找到类定义错误)
当Java虚拟机或者类装载器试图实例化某个类,而找不到该类的定义时抛出该错误。
17、SecturityException(违背安全原则异常)
18、SQLException(操作数据库异常)
19、IOException(输入输出异常)
20、SocketException(通信异常)
21、java.lang.Error(错误)
错误,是所有错误的基类,用于标识严重的程序运行问题,这些问题通常描述一些不应该被应用程序捕获的反常情况。
原因:对系统所访问外部资源,未执行关闭操作,导致外部资源大量浪费,最终可能导致系统无法正常运行;对系统所访问的外部资源关闭次数太多,外部系统无法正常处理;系统访问的外部资源出现异常情况。
解决方法:访问外部资源之前,首先检查该资源(如数据库)是否可正常连接或操作;访问外部资源时,如果进行了连接,一定要关闭操作,并且仅进行一次关闭操作;尽量在同一操作中共享外部资源,以减少该操作对资源的浪费,提高程序的执行效率。