[code="java"]
public class ClassA {
public ClassA()throws Exception{
// TODO Auto-generated constructor stub
try{
throw new RuntimeException("bbbbbbbbbb");
}catch(RuntimeException e){
throw new Exception("cccccccc"+ e.getMessage(),e);
}
}
}
[/code]
[code="java"]
public class CatchExceptionTest {
public static void main(String[] args){
try{
Class throttleClass = Class.forName("ClassA");
Constructor c = throttleClass.getConstructor();
ClassA a = (ClassA)c.newInstance();
}catch(RuntimeException ee){
System.out.println("11111111");
System.out.println(ee.getMessage());
}catch(Exception e){
System.out.println("222222222 " + e.toString());
System.out.println(e.getMessage());
}
}
}
[/code]
求主方法执行的结果, 以及出现的原因。。。
[code="java"]
/**
*/
public class CustomException extends Exception {
/** 自定义错误代码 */
private String errorCode;
public CustomException() {
super();
}
public CustomException(String message, Throwable cause) {
super(message, cause);
}
public CustomException(String message) {
super(message);
}
public CustomException(Throwable cause) {
super(cause);
}
/**
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}
[/code]
// 构造异常
new CustomException("errorA", "异常A", e);
new CustomException("errorB", "异常B", e);
捕捉:
try {
....
} catch (CustomException ce) {
System.out.println(ce.getErrorCode());
}
结果我觉得应该是
[code="java"]
222222222 java.lang.Exception@xxxxxx
222222222ccccccccbbbbbbbbbb java.lang.Excpetion xxx, [/code]
ClassA在初始化构造函数的时候,出发Runtime异常,被捕捉,然后再抛出Exception异常,在CatchExceptionTest被捕捉,然后打印
结果是:
222222222 java.lang.reflect.InvocationTargetException
null
如果ClassA a = (ClassA)c.newInstance();
改为new ClassA();
结果为:
222222222 java.lang.Exception: ccccccccbbbbbbbbbb
ccccccccbbbbbbbbbb
我用的是JDK1.5,是不是版本与你不同
ClassA a = (ClassA) c.newInstance();
之所以后面会输出null,是因为在c.newInstance()调用的代码中被屏蔽了异常
而new ClassA();则直接抛出,所以捕捉到了
ccccccccbbbbbbbbbb
[quote]请问你执行出来的结果是 什么呢 ? [/quote]
是使用JDK1.5执行的结果
e.getMessage()获取不到,但e.getCause()可以捕获到
[quote]e.getCause() 是跟 e。printstacktrace()一样的效果么? [/quote]
不同,前者是获取private Throwable cause; 这个对象
如果 cause 不存在或未知,则返回 null
后者:
将此 throwable 及其追踪输出至标准错误流。此方法将此 Throwable 对象的堆栈跟踪输出至错误输出流,作为字段 System.err 的值。输出的第一行包含此对象的 toString() 方法的结果。剩余行表示以前由方法 fillInStackTrace() 记录的数据。此信息的格式取决于实现,但以下示例是最常见的:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9)
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
会打印出一大堆的信息
前面说的:
[quote]ClassA a = (ClassA) c.newInstance();
之所以后面会输出null,是因为在c.newInstance()调用的代码中被屏蔽了异常 [/quote]
不太对
c.newInstance();捕捉到异常会封装到java.lang.reflect.InvocationTargetException中
当c.newInstance()抛出异常时,会使用
[code="java"]
public InvocationTargetException(Throwable target) {
super((Throwable)null); // Disallow initCause
this.target = target;
}
[/code]
构造函数来封装,即将ClassA的异常存放在InvocationTargetException类中的target对象中
而e.getMessage()是在InvocationTargetException的父父类Throwable中定义的,如下:
[code="java"]
private String detailMessage;
public String getMessage() {
return detailMessage;
}
[/code]
由于异常保存在target中,detailMessage为空,所以会打印出null
继承关系如下:
public class InvocationTargetException extends Exception
public class Exception extends Throwable
可以得到
public class ClassA {
public ClassA()throws Exception{
// TODO Auto-generated constructor stub
try{
throw new RuntimeException("bbbbbbbbbb");
}catch(RuntimeException e){
throw new Exception("cccccccc"+ e.getMessage(),e);
}
}
}
中的 "cccccccc"+ e.getMessage()
[quote]我的 结果 是 22222222java.lang.reflect.ClassNotFoundException
ClassA [/quote]
那是找不到ClassA这个类。
Class.forName("ClassA"); 这里要加上包名,如 Class.forName("org.test.ClassA");
[quote]但是想上面那种掩盖异常信息 只会出现在 反射调用中么, 如果平常自定的方法调用也会掩盖异常信息, 能给出个示列么 ? [/quote]
在MVC中,一般有Action、Service、DAO三层
DAO抛异常Service可以捕捉到
Service抛异常Action可以捕捉到
这种是没问题的
上面这种情况,由于不是调用自己的方法,处理异常的方式不是自己控制的而已。
事实上不会被屏蔽,最多就被封装到e.getCause() 对应的对象中
所以通过e.getMessage()或e.getCause()是可以获取抛出的信息的
[code]
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
public Exception() {
super();
}
public Exception(String message) {
super(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
}
.....
[/code]
只要throw new xxxxException(String) 就能取到了。
而所有的XXXException又是Exception的子类
[quote]但是想上面那种掩盖异常信息 只会出现在 反射调用中么, 如果平常自定的方法调用也会掩盖异常信息, 能给出个示列么 ?[/quote]
c.newInstance(); 会在遇到异常时封装一次。而直接调用就滑谁封装了。
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.zsoft.test.Test.main(Test.java:87)
Caused by: java.lang.Exception: ccccccccbbbbbbbbbb
at com.zsoft.test.ClassA.(Test.java:133)
... 5 more
Caused by: java.lang.RuntimeException: bbbbbbbbbb
at com.zsoft.test.ClassA.(Test.java:131)
... 5 more
如果是你自己定的类,自己捕捉异常,只需要打印出你自己定义的信息:
[code="java"]
public class A {
public A() throws Exception {
try {
throw new RuntimeException("A-RuntimeException");
} catch (RuntimeException e) {
throw new Exception("A异常信息 : " + e.getMessage(), e);
}
}
}
[/code]
[code="java"]
public class B {
public B() throws Exception {
try {
new A();
} catch (Exception e) {
throw new Exception("B异常信息 : " + e.getMessage(), e);
}
}
}
[/code]
[code="java"]
public class C {
public static void main(String[] args) {
try {
new B();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
[/code]
结果:
B异常信息 : A异常信息 : A-RuntimeException
这个就是你想要的了
1、
ClassA a = (ClassA) c.newInstance();
使用的异常封装方法是:
[code="java"]
public InvocationTargetException(Throwable target) {
super((Throwable)null); // Disallow initCause
this.target = target;
}
[/code]
这个需要获取到target对象,才能获取到我们写入的提示信息
2、而一般我们用的方法是:
[code="java"]
throw new Exception("B异常信息 : " + e.getMessage(), e);
[/code]
构造函数为
[code="java"]
public Exception(String message, Throwable cause) {
super(message, cause);
}
[/code]
所以这个用getMessage()可以直接获取到信息
[quote]所以这个detailMessage的掩盖 归结为c.newInstance()的源码实现问题,是则这样吧 ? [/quote]
对!
[quote]就是说什么情况下 我们需要 使用 "" + e.getCause().getMessage() 是取决于前面try{}块里调用的方法, 是吧?[/quote]
不对。
e.getCause() 是得到谁引起这个异常,还可以 e.getCause().getCause(),直接找到最根本那个异常。
任何异常都有 getMessage()
[quote]就是说什么情况下 我们需要 使用 "" + e.getCause().getMessage() 是取决于前面try{}块里调用的方法, 是吧?[/quote]
取决于
try {
}
块内封装异常的方式(一般是通过不同的构造函数实现)
如果我们自定义异常类,继承Exception或RuntimeException,我们也可以自定义其他属性来封装我们的异常信息,怎么获取也可以自定义
[quote]最后一条语句 打印出来的 e.getMessage()是为空的呀[/quote]
这个e是 java.lang.reflect.InvocationTargetException ,它的 message 属性为 null 。