有个java 异常问题不解。。

[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);
    }

    /**

    • 添加一个自定义的code属性
    • @param errorCode
    • @param message
    • @param cause */ public CustomException(String errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = errorCode; }

    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 。