我觉得异常。fillInStackTrace应的回报的异常或衍生出异常的对象。考虑到两个职能如下,

public static void f() throws Throwable {
    try {
        throw new Throwable();
    } catch (Exception e) {
        System.out.println("catch exception e");
        e.printStackTrace();
    } 
}
public static void g() throws Throwable {
    try {
        try {
            throw new Exception("exception");
        } catch (Exception e) {
            System.out.println("inner exception handler");
            throw e.fillInStackTrace();
        }
    } catch (Exception e) {
        System.out.println("outer exception handler");
        e.printStackTrace();
    }
}
  1. exception handler 不可能赶上 new Throwable() 在第一个函数 f().
  2. exception handler 可以赶上的 e.fillInstackTrace() 在第二个函数 g().
  3. 但第二个函数 g() 仍然需要 throws Throwable.这真的是奇怪的,因为我们能赶上 e.fillInstackTrace().

所以我的问题是,为什么不例外。fillInStackTrace回报的异常或例外的来源,而不是发展这样一个奇怪法?

编辑:
澄清 我的问题:我的意思是"怪的语法"的

  1. 由于 Exception.fillInStackTrace() 返回 Throwable 参考,例外处理其收到 Exception 应当参考不能够赶上的例外。因为java不允许implict垂头丧气,它应该是这样的 return (Exception)e.fillInstackTrace().
  2. 由于它的设计,例外处理程序接收的 Exception 参考可以处理 Throwable 例外的是,没有需要标记的方法 g()Throwable 例外。但java编译器将强制执行我们这样做。

谢谢。

有帮助吗?

解决方案

它实际上是容易回答你的问题开始与问题2。

你问:2.由于它的设计,例外处理程序接收的异常引用可以处理的抛出的例外,没有需要标记的方法克()throws抛出的例外。但java编译器将强制执行我们这样做。

回答:实际上,抓(例外e)无法赶上抛出.试试这个:

try {
       Throwable t = new Throwable();
       throw t.fillInStackTrace();
} catch (Exception e) {
    System.out.println("outer exception handler");
    e.printStackTrace();
} 

你会看到的赶条款并未赶上扔在这种情况。

原因的捉条款的工作在你g()方法是,当你调用 throw e.fillInStackTrace(), ,呼吁fillInStackTrace实际上返回一个例外(这是因为e是一个例外本身)。由于异常的子抛出,这并不违背《宣言》的fillInStackTrace.

现在对第一个问题

你问:1.由于例外。fillInStackTrace()返回抛出的参考,例外处理其收到的例外应当参考不能够赶上的例外。因为java不允许implict垂头丧气,它应该是这样的返回(例外)e。fillInstackTrace().

回答:这不正是一个隐含的垂头丧气。认为这是一个变化的过载。

让我们说你有

void process(Throwable t){
   ...
}
void process(Exception e){
  ...
} 

如果你打电话 process(someObject), 它将在运行时确定是否具有第一或第二工艺方法被称为。同样,是否抓住(例外e)条款可以赶上你扔将在运行时确定,基于是否你扔一个异常或抛出.

其他提示

我很疑惑你的问题。还有清楚的东西有关java例外/例外处理,你不理解。所以让我们从头开始。

在爪哇,所有例外情况(在这个意义上,用这个术语是在爪哇语言的规范)的情况的某些类子类的 java.lang.Throwable.有两个(并且只有两个)直接的子抛出;即 java.lang.Exceptionjava.lang.Error.实例,所有这些类...包括抛出的实例和错误...被称为例外,在捷尔思.

一个例外处理程序渔获物的例外(在捷尔思义),被分配兼容的例外类型中使用的 catch 《宣言》。所以,例如:

try {
    ....
} catch (Exception ex) {
    ...
}

将捕获的任何例外扔的 try 方框,是一个实例 java.lang.Exception 或者直接或间接的子类型的 java.lang.Exception.但它不会赶上的一个实例 java.lang.Throwable, 因为这是(显然)不上述之一。

在另一方面:

try {
    ....
} catch (Throwable ex) {
    ...
}

抓住的一个实例 java.lang.Throwable.

审查您的例子,在此,很明显为什么 f 方法不是追赶抛出的实例:它不匹配的异常类型的捕条款!相比之下,在该 g 方法的异常实例的例外类型的捕条款,并因此被捕。

我不明白你在说什么关于需要扔一个抛出在 g.首先,事实上,该法宣布,它将引发抛出 不不 意思是,这实际上需要把它扔了。所有这说的是它 可能会 扔东西可分配给抛出...可能在未来的某一版本 g 法。其次,如果你要加入 throw e; 外赶块, 可以扔的东西是可分配给抛出.

最后,它通常是一个糟糕的想法是创建的实例抛出的、例外、错误和异常.你必须非常小心,何时以及如何赶上他们。例如:

try {
     // throws an IOException if file is missing
    InputStream is = new FileInputStream("someFile.txt");
    // do other stuff
} catch (Exception ex) {
    System.err.println("File not found");
    // WRONG!!!  We might have caught some completely unrelated exception;
    // e.g. a NullPointerException, StackOverflowError, 
}

编辑 -在响应运的评论:

但我扔扔e。fillInStackTrace();应该是一个Intance的抛出,不例外!

对如果是的话,为什么不试说,具体而言,返回的对象是异常对象你打电话的方法。目的 fillInStacktrace() 方法是填写这堆跟踪现有的对象。如果你想要一个不同的例外,应该使用 new 创建一个。

实际上,我的意思是外的例外处理程序不应该抓住抛出扔扔e。fillInStackTrace().

我已经解释了为什么它不-因为抛出的实际上是原来的例外。是不是有什么有关我的解释,你不了解或者是你只是说你不喜欢的方式,Java定义?

编辑2

如果该外的例外处理程序可以处理的抛出的例外,为什么我们必须指定方法克会抛抛出异常

你误解了我是说...这是如果你有没有扔一个例外,那么 throws Throwable 不会是多余的。另一方面,我最后想我明白您的投诉。

我认为,关键在您的投诉是,你会得到一个编辑错误:

public void function() throws Exception {
    try {
        throw new Exception();
    } catch (Exception ex) {
        throw ex.fillInStackTrace();
        // according to the static type checker, the above throws a Throwable
        // which has to be caught, or declared as thrown.  But we "know" that the 
        // exception cannot be anything other than an Exception.
    }
}

我可以看到,这是有点意外。但这是不可避免的我很害怕。有没有办法(短的一个重大改变Java的类型系统),可以声明的签名 fillInStacktrace 这将工作在所有情况。例如,如果移动《宣言》的方法的异常类,你会只是重复相同的问题与亚型的例外。但如果你试图表达的签名,使用一般类型参数,它将意味着使所有亚类的抛出明确的通用类型。

幸运的是,治疗是真的很简单;投的结果 fillInStacktrace() 如下:

public void function() throws Exception {
    try {
        throw new Exception();
    } catch (Exception ex) {
        throw (Exception) (ex.fillInStackTrace());
    }
}

以及最后一点是,它是非常不寻常的应用程序明确地呼叫 fillInStacktrace().鉴此,它将根本就没有值得Java的设计师有"打掉他们的胆量",试图解决这个问题。特别是因为它是真的只有一个小小的不便...在大多数。

我想你得问弗兰克喊(的 @authorjava.lang.Exception).正如其他人所说的那样, fillInStackTrace() 宣布 Throwable 和记录返回 this, ,使其返回的类型必须 Throwable.它只是继承的 Exception.弗兰克可能拥有复盖它 Exception, 像这样的:

public class Exception extends Throwable{
    /**Narrows the type of the overridden method*/
    @Override
    public synchronized Exception fillInStackTrace() {
        super.fillInStackTrace();
        return this;
    }
}

...但他没有。前Java1.5,原因是它会产生一个编辑错误。在1.5及以后,协变回归类型 都是允许的 和以上是合法的。

但是我的猜测是,如果上述复盖的存在,你会然后可以问为什么 RuntimeException 没有一个类似的复盖,为什么 ArrayStoreException 没有复盖该复盖,等等。因此弗兰克和朋友可能只是不想写那些数以百计的相同复盖。

值得注意的是,如果你处理你自己的定义的异常类,可以很容易地复盖 fillinStackTrace() 方法,因为我已经做了以上,并得到较窄的类型你之后。

使用仿制药,可以想象一下增加的声明 Throwable 为:

public class Throwable<T extends Throwable<T>>{
    public synchronized native T fillInStackTrace();
}

...但是这不是真的令人满意,原因是超出范围的这种答案。

fillInStackTrace 返回的参考相同的对象。它的方法链接到允许再扔 Exception 和重置异常的堆踪。

public static void m() {
    throw new RuntimeException();

}

public static void main(String[] args) throws Throwable {
    try {
        m();
    } catch (Exception e) {
        e.printStackTrace();
        throw e.fillInStackTrace();
    }
}

该方法返回型只能基本类型是 Throwable.它可以generified这样的方法返回的参数化的类型。但是,情况并非如此。

RuntimeException e = new RuntimeException();
Throwable e1 = e.fillInStackTrace();
System.out.println(e1.getClass().getName()); //prints java.lang.RuntimeException
System.out.println(e == e1); //prints true

fillInStackTrace() 定义 Throwable, ,不 Exception.

不是所有亚类的 Throwable 例外情况(Error, 为例)。尽 Throwable 感到关切的是,唯一可以保证有关返回的价值 fillInStackTrace() 是,它是一个实例 Throwable (因为它只是返回同一目的,作为 Chandra Patni 注意到).

实际上 fillInStackTrace 返回同一目的是援引。

e.fillInStackTrace == e 总是真实的

这只是一个 快捷方式, 你也可以写信

    } catch (Exception e) {
        System.out.println("inner exception handler");
        e.fillInStackTrace();
        throw e;
    }

或者使用一个铸造

    throw (Exception) e.fillInStackTrace();

顺便说一句,情况与此相同 initCause().

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top