Java的Try Catch块

3

我最初在大学学习VB.NET编程。现在决定转向Java,并有一些疑问。在VB中,try catch语句的编写格式如下:

try
Catch ex as exception
finally
End catch

但是从 Java 网站 (https://docs.oracle.com/javase/tutorial/essential/exceptions/putItTogether.html) 中,我发现在 Java 中你可以这样使用两个 catch:
    try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}

我希望有人能够解释一下在Java中为什么需要两个catch,以及各自的作用是什么。谢谢。

1
一段代码可能会生成N种类型的异常,您可以为不同的异常定义不同的流程。 - kosa
1
两个catch块不能是相同的异常类型(这将导致编译时错误)-它们必须是不同的类型,您希望以不同的方式处理它们。 - Andy Turner
你不需要两个。你可以有1..N个捕获不同类型异常的catch语句。 - Jeroen Vannevel
2个回答

6
在Java中,您可以使用多个catch块。但这并不意味着您必须这样做。这取决于您在try块中编写的代码以及它可能抛出的受检查Exception的数量(甚至是未检查的Exception,如果您真的想捕获它们,通常情况下你不需要这样做)。使用单个处理程序来处理一般的Exception(或更糟糕的是Throwable,这也将捕获RuntimeExceptionError)是一种不好的做法:
try {
    // stuff that throws multiple exceptions
}
// bad
catch (Exception e) {
    // TODO
}

良好的做法是捕获所有可能抛出的已检查Exception

如果它们中的一些在继承方面有关联,请始终首先捕获子类(即更具体的Exception),否则您的代码将无法编译:

try {
    // stuff that throws FileNotFoundException AND IOException
}
// good: FileNotFoundException is a child class of IOException - both checked
catch (FileNotFoundException fnfe) {
    // TODO
}
catch (IOException ioe) {
    // TODO
}

此外还要看一下Java 7的多异常捕获块。在这里,不相关的异常可以用|分隔符一次性捕获所有异常类型:(参见此处)
try (optionally with resources) {
    // stuff that throws FileNotFoundException and MyOwnCheckedException
}
// below exceptions are unrelated
catch (FileNotFoundException | MyOwnCheckedException e) {
    // TODO
}

注意

在您提供的示例中,下面的第一段代码“把所有东西放在一起”可以说是次优的:它确实捕获了潜在抛出的Exception,但其中一个异常是IndexOutOfBoundsException,它是RuntimeException(未检查异常),理论上不应该被处理。

相反,在迭代列表时,应该用指向列表大小的引用替换变量SIZE(或者可能是常量),即list.size(),以防止抛出IndexOutOfBoundsException

我猜这只是为了提供一个例子。


2

我修改了链接页面上的代码,只有一个例外。问题在于,在这种情况下,您将无法知道异常是由于IndexOutOfBoundsException还是IOException而导致的,只能知道发生了异常。

import java.io.*;

import java.util.List;
import java.util.ArrayList;

public class ListOfNumbers {

    public static void main(String... s) {
        ListOfNumbers lon = new ListOfNumbers();
        lon.writeList();
    }

    private List<Integer> list;
    private static final int SIZE = 10;

    public ListOfNumbers() {
        list = new ArrayList<Integer>(SIZE);
        for (int i = 0; i < SIZE; i++) {
            list.add(new Integer(i));
        }
    }

    public void writeList() {
        PrintWriter out = null;

        try {
            System.out.println("Entering" + " try statement");

            out = new PrintWriter(new FileWriter("e://OutFile.txt"));
            for (int i = 0; i < SIZE; i++) {
                out.println("Value at: " + i + " = " + list.get(i));
            }
        } catch (Exception e) {
            System.err.println("Caught Exception: " + e.getMessage());

        } finally {
            if (out != null) {
                System.out.println("Closing PrintWriter");
                out.close();
            } else {
                System.out.println("PrintWriter not open");
            }
        }
    }
}

让我们了解这个概念,更好地知道代码为什么会因为哪种特定类型的异常而失败,无论是IndexOutOfBoundsException还是IOException。

现在,带有不同异常处理的代码如下:

import java.io.*;

import java.util.List;
import java.util.ArrayList;

public class ListOfNumbers {

    public static void main(String... s) {
        ListOfNumbers lon = new ListOfNumbers();
        lon.writeList();
    }

    private List<Integer> list;
    private static final int SIZE = 10;

    public ListOfNumbers() {
        list = new ArrayList<Integer>(SIZE);
        for (int i = 0; i < SIZE; i++) {
            list.add(new Integer(i));
        }
    }

    public void writeList() {
        PrintWriter out = null;

        try {
            System.out.println("Entering" + " try statement");

            out = new PrintWriter(new FileWriter("e://OutFile.txt"));
            for (int i = 0; i < SIZE; i++) {
                out.println("Value at: " + i + " = " + list.get(i));
            }
        } catch (IndexOutOfBoundsException e) {
            System.err.println("Caught IndexOutOfBoundsException: " +
                               e.getMessage());

        } catch (IOException e) {
            System.err.println("Caught IOException: " + e.getMessage());

        } finally {
            if (out != null) {
                System.out.println("Closing PrintWriter");
                out.close();
            } else {
                System.out.println("PrintWriter not open");
            }
        }
    }
}

在这里,我们可以知道它是否因为在以下位置创建文件而失败:

e://OutFile.txt 驱动器不在我的系统上

错误消息如下:

捕获异常: e:\OutFile.txt (系统找不到指定的路径) 进入try语句PrintWriter未打开

下一个案例

现在,当我注释掉以下行时:

list.add(new Integer(i));

import java.io.*;
import java.util.List;
import java.util.ArrayList;

    public class ListOfNumbers {

        public static void main(String... s) {
            ListOfNumbers lon = new ListOfNumbers();
            lon.writeList();
        }

        private List<Integer> list;
        private static final int SIZE = 10;

        public ListOfNumbers() {
            list = new ArrayList<Integer>(SIZE);
            for (int i = 0; i < SIZE; i++) {
                //    list.add(new Integer(i));
            }
        }

        public void writeList() {
            PrintWriter out = null;

            try {
                System.out.println("Entering" + " try statement");

                out = new PrintWriter(new FileWriter("OutFile.txt"));
                for (int i = 0; i < SIZE; i++) {
                    out.println("Value at: " + i + " = " + list.get(i));
                }
            } catch (IndexOutOfBoundsException e) {
                System.err.println("Caught IndexOutOfBoundsException: " +
                                   e.getMessage());

            } catch (IOException e) {
                System.err.println("Caught IOException: " + e.getMessage());

            } finally {
                if (out != null) {
                    System.out.println("Closing PrintWriter");
                    out.close();
                } else {
                    System.out.println("PrintWriter not open");
                }
            }
        }
    }

那么它明确表示它因为索引越界异常而失败

进入try语句 捕获IndexOutOfBoundsException: Index: 0, Size: 0 关闭PrintWriter

因此,为了正确高效地调试应用程序,这是很好的。

我已经为其他类型的异常创建了条件

NoClassDefFoundError

java.lang.NoClassDefFoundError: ListOfNumbers
Caused by: java.lang.ClassNotFoundException: stackprac.ListOfNumbers
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Exception in thread "main" Process exited with exit code 1.

感谢您的回答。 - User59

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接