Java异常处理机制

142 阅读7分钟

java中的异常分为哪些种类?

按照异常需要处理的时机分为编译时异常(也叫强制性异常)也叫CheckedException和运行时异常(也叫非强制性异常)也叫RuntimeException。只有java语言提供了Checked异常,java认为Checked异常都是可以被处理掉的异常,所以java程序必须显示处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误无法编译。这体现了java的设计哲学:没有完善错误处理的代码根本没有机会被执行。对Checked异常处理的方法有两种:

1:当前方法指导如何处理异常,则用try...catch块来处理改异常
2:当前方法不知道如何处理异常,则在定义该方法上声明抛出该异常

运行时异常只有当代码在运行时才发生的异常,编译时不需要try...catch。Runtime如除数是0和数组下标越界等,其产生频繁,处理麻烦,若显示声明或者捕捉将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将他们交给缺省的异常处理程序。当然如果你有处理要求也可以显示的捕捉他们。

error和exception的区别?

Error类和exception类的父类都是Throwable类,他们的区别如下:

Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等,对于这类错误导致的应用程序中断,仅靠程序本身无法恢复和预防,遇到这样的错误,建议程序终止。

Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不是应该随意终止异常。

Exception类又分为运行时异常(Runtime Exception)和受检查的异常(Checked Exception),运行时异常;ArithmaticExceptioin,IllegalArgumentException,编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用try...catch捕获,要么用throws字句声明抛出,交给他的父类处理,否则编译不会通过。

java的异常处理机制

java对异常进行分类,不同类型的异常分别用不同的java类表示,所有异常的根类为java.lang,Throwable,Throwable下面又派生了两个子类:Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题。Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷导致的问题,也就是软件开发人员考虑不周导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),控指针异常(NullPointerException),类转换异常(ClassCastException);普通异常是运行环境的变化活异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try...catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器强制使用try..catch处理或者throws声明。

请写出你最常见的五个runtime Exception

1:NullPointerException

2:ClassNotFoundException

3:NumberFormatException

4:IndexOutOfBoundsException

5:IllegalArgumentException

6:ClassCastException

7:NoClassDefFoundException

8:SQLException

9:InstantiationException 实例化异常

10:NoSuchMethodException 方法不存在异常

throw和throws的区别

throw:

1:throw用在方法体内,表示抛出异常,由方法体内的语句处理
2:throw是具体向外抛出异常的动作,所以他抛出的是一个异常实例,执行throw一定是抛出了某种异常。

throws:

1:throws语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理。
2:throws主要是声明这个方法会抛出某种类型的异常,让他的使用者要知道需要捕获的异常的类型。
3:throws表示出现异常的一种可能性,并不一定会发生这种异常。

final,finally,finalize的区别

final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被修饰的类不可继承。

finally:异常处理结构的一部分,表示总是执行

finalize:Object类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。该方法更像是一个对象生命周期的临终方法,当该方法系统调用则代表该对象即将死亡,但是需要注意的是,我们主动行为上上调用该方法并不会导致该对象“死亡”,这是一个被动的方法(其实就是回调方法)不需要我们调用。

String,StringBuilder,StringBuffer的区别?

java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,他们都可以存储和操作字符串,区别如下:

1:String是只读字符串,也就意味着String引用的字符串内容是不能被改变的,初学者可能会有这样的误解:

String str = "abc";
str = "bcd";

如上,字符串str明明是可以改变的啊。其实不然,str仅仅是一个引用对象,它指向一个字符串对象“abc”。第二行代码的含义是让str重新指向了一个新的字符串”bcd“对象,而"abc"对象并没有任何改变,只不过该对象已经成为一个不可及对象罢了。

2:StringBuffer/StringBuilder表示的字符串对象可以直接进行修改。

3:StringBuilder是java5引入的,他和StringBuffer的方法完全相同,区别在于他是在单线程环境下使用的,因为他所有的方法都没有被synchronized修饰,因此理论上他的效率比StringBuffer要高。

什么情况下用"+"运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?

字符串是java程序中最常用的数据结构之一,在java中String类已经重载了"+"。也就是说,字符串可以直接使用”+“进行连接,如下代码所示:

String s = "abc" + "ddd"; 

但这样做真的好吗?当然,这个问题不能简单的回答 yes or no。要根据具体的情况来定。在java中提供了一个StringBuilder类(这个类只在j2se5及以上版本提供,以前的版本使用StringBuffer类),这个类也可以起到"+"的作用,那么我们该用哪个呢?

下面让我们先看看如下代码:

package string;
public class TestSimplePlus{
	public static void main(String[] args){
    String s = "abc";
        String ss = "ok" + s + "xyz" + 5;
        System.out.pintln(ss);
    }
}

上面的代码将会输出正确的结果,从表面看,对字符串和整型使用“+”号并没有什么区别,但事实真的如此吗?

下面让我们来看看这段代码的本质:

我们首先使用反编译工具(如jdk带的javap,或者jad)将TestSimplePlus反编译成JavaByteCode。其中的奥秘就一目了然了,在本文中使用jad来反编译,命令如下:
jad -o -a -s d.java TestSimplPlus.class

大家可以看到,虽然编译器将"+"转换成了StringBuilder,但是穿件StringBuilder对象的位置却在for语句内部,这就意味着每执行一次循环,就会创建一个StringBuilder对象,虽然java有垃圾回收器,但这个回收器的工作时间是不定的,如果不断产生这样的垃圾,那么仍然会占用大量的资源,解决这个问题的方法就是在程序中直接使用StringBuilder来链接字符串。

在使用StringBuilder时要注意,尽量不要"+"和StringBuilder混着用,否则会穿件更多的String'Builder对象 StringBuffer和StringBuilder的功能基本是一样的,只是StringBuffer是线程安全的,而StringBuilder不是线程安全的,因此StringBuilder的效率会更高。