7: dup
8: ldc #4 // String
10: invokespecial #5 // Method java/io/FileReader."
13: invokespecial #6 // Method java/io/BufferedReader."
16: astore_0
17: aconst_null
18: astore_1
19: aload_1
20: invokeinterface #7, 1 // InterfaceMethod java/sql/Connection.createStatement:()Ljava/sql/Statement;
25: astore_2
26: goto 34
29: astore_0
30: aload_0
31: invokevirtual #10 // Method java/lang/Exception.printStackTrace:()V
34: return
Exception table:
from to target type
0 26 29 Class java/io/IOException
0 26 29 Class java/sql/SQLException
使用两个catch生成的字节码
[java]
public static void second();
Code:
0: new #2 // class java/io/BufferedReader
3: dup
4: new #3 // class java/io/FileReader
7: dup
8: ldc #4 // String
10: invokespecial #5 // Method java/io/FileReader."
13: invokespecial #6 // Method java/io/BufferedReader."
16: astore_0
17: aconst_null
18: astore_1
19: aload_1
20: invokeinterface #7, 1 // InterfaceMethod java/sql/Connection.createStatement:()Ljava/sql/Statement;
25: astore_2
26: goto 42
29: astore_0
30: aload_0
31: invokevirtual #11 // Method java/io/IOException.printStackTrace:()V
34: goto 42
37: astore_0
38: aload_0
39: invokevirtual #12 // Method java/sql/SQLException.printStackTrace:()V
42: return
Exception table:
from to target type
0 26 29 Class java/io/IOException
0 26 37 Class java/sql/SQLException
switch那里生成的字节码不太明显看出来优化在哪里,这个很明显。首先,字节码长度变少 其次,从最后可以看出,target type都指向29行,两个catch会指向不同的行~
2、用更包容性的类型检查来重新抛出异常
在方法的声明上,使用throws语句时,你可以指定更加详细的异常类型。
[java]
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
这个例子,try块中只能抛出两种异常,但是因为catch里的类型是 Exception,在java SE7以前的版本中,在方法声明中throws 只能写Exception,但是在java SE7及以后的版本中,可以在throws后面写 FirstException和SecondException——编译器能判断出throw e语句抛出的异常一定来自try块,并且try块只能抛出FirstException和SecondException。
[java]
public static void reThrowException(String exceptionName)
throws FirstException, SecondException{
try {
if ("first".equals(exceptionName))
throw new FirstException();
else
throw new SecondException();
} catch (Exception e) {
throw e;
}
}
所以尽管catch里的异常类型是Exception,编译器仍然能够知道它是FirstException和 SecondException的实例。怎么样,编译器变得更智能了吧。
但是,如果在catch里对异常重新赋值了,在方法的throws后无法再向上面那样写成FirstException和SecondExcep