1.使用try...catch捕获异常
public void update(){
session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
try{
Dage dage=session.get(Dage.class,1);
dage.setName("DAGE");
session.update(dage);
transaction.commit();
}catch (Exception e){
transaction.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
不管程序代码块是否处于try块中,甚至包括catch块中代码,只要执行该代码块时出现了异常,系统都会自动生成一个异常对象。
2.异常类的继承体系:
Java把所有非正常情况分为两种:异常(Exception)和错误(Error),都继承Throwable父类;
3.访问异常信息:
如果程序需要在catch块中访问异常对象的相关信息,可以通过调用catch后异常形参的方法来获得,当Java运行时决定调用某个catch块来处理该异常对象时,会将该异常对象赋给catch块后的异常参数,程序就可以通过该参数来获得该异常的相关信息;所有异常对象都包含如下几个方法:
public void t(){
try {
FileInputStream fis=new FileInputStream("a.txt");
}catch (Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
4.使用finally回收资源
这些物理资源包括(数据库连接、网络连接和磁盘文件),这些都需要显示的回收;Java的垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占有的内存;
finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。
若在finally块中也有return语句时,则系统不会调回去执行try、catch块里的任何代码;
异常被分为两大类:Checked异常和Runtime异常(运行时异常):
对于Checked异常的处理方式有两种:
使用throws声明抛出异常:
使用throws声明抛出异常的思路是:当前方法不知道应该如何处理这种类型,该异常由它的上一级调用者处理,如果main方法也不知道应该如何处理这种类型的异常,也可以使用throws声明抛出异常,该异常交给JVM处理。JVM对异常的处理方法是:打印异常跟踪信息,并终止程序运行,
如果某段代码中调用了一个带throws声明的方法,该方法声明抛出了Checked异常,这表明该方法希望它的调用者来处理该异常,即要么捕获要么抛出;
public void t() throws FileNotFoundException {
t1();
try {
FileInputStream fis=new FileInputStream("a.txt");
}catch (Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public void t1() throws FileNotFoundException {
FileInputStream fis=new FileInputStream("a.txt");
}
使用throws声明抛出异常时:子类方法中抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相等,子类不允许比父类声明抛出更多的异常;
Throws抛出异常的规则:
1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。
2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误
3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。
4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。
使用throw抛出异常:
当程序出现错误的时,系统会自动抛出异常;除此之外,Java也允许程序自动抛出异常,自行抛出异常使用throw语句完成;throw语句抛出的不是异常类,而是一个异常实例且每次只能抛出一个异常实例;
当Java运行时接受到用户自行抛出的异常时,一样会终止当前的执行流,调到对应的catch块中,由该catch块来处理该异常;也就是说,不管是系统自动抛出的异常,还是程序员手动抛出的异常,Java运行时环境对异常的处理没有任何差别。
如果throw语句抛出的异常是Checked异常,则该throw语句要么在try块里,显示捕获该异常,要么放在一个带throws声明抛出的方法中,即把该异常交给调用者处理;若是Runtime异常,则该语句无需放在try块里,也无须放在带throws声明抛出的方法中;程序即可以显示的用try...catch来捕获,并处理该异常,也可以完全不理会该异常,把该异常交给该方法的调用者处理;
用户自定义异常都应该继承Exception基类(或Runtime),定义异常类时通常需要提供两种构造器:一个无参数的构造器,另一个是带一个字符串的构造器,这个字符串将作为该异常对象的详细说明(即getMessage方法的返回值)
package exception;
public class AuctionException extends Exception {
public AuctionException(){}
public AuctionException(String msg){
super(msg);
}
}
catch和throw同时使用:
以上的异常处理方式有两种:
实际中则复杂一点:当一个异常出现时,单靠某个方法无法完全处理该异常,必须由几个方法的协作才可以完全处理该异常;即异常出现在当前方法中,程序只对异常进行部分处理,还有些处理需要在该方法的调用者中才能完成,所以应该再次抛出异常,让调用者捕获;
package exception;
public class TestAuction {
private double initPrice=10.0;
public void bid(String bidPrice)throws AuctionException{
double d=0.0;
try {
d=Double.parseDouble(bidPrice);
}catch (Exception e){
e.printStackTrace();
throw new AuctionException("必须是数值");
}
}
public static void main(String[] args) {
TestAuction testAuction=new TestAuction();
try{
testAuction.bid("qww");
}catch (AuctionException a){
System.out.println(a.getMessage());
}
}
}
应用场景:异常需要封装,但是仅仅封装还是不够的,还需要传递异常。一个系统的友好型的标识,友好的界面功能是一方面,另一方面就是系统出现非预期的情况的处理方式了。
public class AuctionException extends Exception {
public AuctionException(){}
public AuctionException(String msg){
super(msg);
}
public AuctionException(Throwable t){
super(t);
}
}
public class TestAuction {
private double initPrice=10.0;
public void bid(String bidPrice)throws AuctionException{
double d=0.0;
try {
d=Double.parseDouble(bidPrice);
}catch (Exception e){
e.printStackTrace();
//throw new AuctionException("必须是数值");
throw new AuctionException(e);
}
}
public static void main(String[] args) {
TestAuction testAuction=new TestAuction();
try{
testAuction.bid("qww");
}catch (AuctionException a){
System.out.println(a.getMessage());
}
}
}
小结:
runtimeException子类:
1、 java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
5、java.lang.NegativeArraySizeException 数组长度为负异常
6、java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常
7、java.lang.SecurityException 安全性异常
8、java.lang.IllegalArgumentException 非法参数异常
IOException:
IOException:操作输入流和输出流时可能出现的异常。
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常
其他:
ClassCastException 类型转换异常类
ArrayStoreException 数组中包含不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不允许访问某类异常
InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常;