Java ClassNotFoundException被神奇地取消选中

Java ClassNotFoundException被神奇地取消选中,java,exception,Java,Exception,我的主辅助线程如下所示: public final class Worker implements Runnable { @Override public void run() { try { _run(); } catch (RuntimeException e) { // Cleanup carefully } } private void _r

我的主辅助线程如下所示:

public final class Worker
implements Runnable {

    @Override
    public void run() {
        try {
            _run();
        }
        catch (RuntimeException e) {
            // Cleanup carefully
        }
    }

    private void _run() {
        // do work here
    }
}
想象一下当
Thread.UncaughtExceptionHandler
报告了
java.lang.ClassNotFoundException
的一个未捕获的实例时,我的惊讶,这是一个已检查的异常

(根本原因是另一个问题:我们在运行时覆盖了开发环境中的JAR文件。)

在我的书中,这看起来像一个。为什么这个异常不是RuntimeException

样本跟踪(消毒):

原因:java.lang.ClassNotFoundException:xyz
在java.net.URLClassLoader$1.run(URLClassLoader.java:369)
在java.net.URLClassLoader$1.run(URLClassLoader.java:361)
位于java.security.AccessController.doPrivileged(本机方法)
位于java.net.URLClassLoader.findClass(URLClassLoader.java:360)
位于java.lang.ClassLoader.loadClass(ClassLoader.java:424)
位于sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
位于java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 10多
原因:java.util.zip.ZipException:读取zip文件时出错
位于java.util.zip.ZipFile.read(本机方法)
access$1400(ZipFile.java:61)
位于java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:717)
位于java.util.zip.ZipFile$zipfileInflatierInputStream.fill(ZipFile.java:420)
位于java.util.zip.InflateInputStream.read(InflateInputStream.java:158)
位于java.util.jar.Manifest$FastInputStream.fill(Manifest.java:441)
位于java.util.jar.Manifest$FastInputStream.readLine(Manifest.java:375)
位于java.util.jar.Manifest$FastInputStream.readLine(Manifest.java:409)
位于java.util.jar.Attributes.read(Attributes.java:376)
位于java.util.jar.Manifest.read(Manifest.java:199)
位于java.util.jar.Manifest。(Manifest.java:69)
位于java.util.jar.JarFile.getManifestFromReference(JarFile.java:199)
位于java.util.jar.JarFile.getManifest(JarFile.java:180)
位于sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:780)
位于java.net.URLClassLoader.defineClass(URLClassLoader.java:422)
在java.net.URLClassLoader.access$100(URLClassLoader.java:73)
在java.net.URLClassLoader$1.run(URLClassLoader.java:367)
... 还有16个

没错,ClassNotFoundException不是运行时异常,但您的代码不需要捕获它,因为虚拟机是尝试加载所有所需类的机器

如果您的代码试图通过类加载器加载一个类,则必须捕获ClassNotFound,如下所示

package a;

public class B {

    public void testLoadClass() {

        try {
            ClassLoader.getSystemClassLoader().loadClass("java.util.ArrayList");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
我认为,为了在编译时了解不存在的类,检查异常的事实是可以的。通过这种方式,您可以控制流代码。如果该异常不是已检查的异常,则在编译时将丢失代码控制。这只是一种观点

为什么这个异常不是运行时异常

这是
java.lang.ClassNotFoundException

java.lang.Object
 java.lang.Throwable
  java.lang.Exception
   java.lang.ReflectiveOperationException
     java.lang.ClassNotFoundException
正如您所看到的,它没有以任何方式扩展具有此层次结构的
运行时异常

java.lang.Object
 java.lang.Throwable
  java.lang.Exception
   java.lang.RuntimeException
如果你想抓住他们两个<代码>捕获异常

如果你想抓住一切<代码>可丢弃的捕获物


最后,如果您想了解更多有关层次结构和继承的信息,可以从这里开始:

运行时异常实际上是意外的异常。(例如,
NullPointerException
索引自动边界异常
),通常由错误引起。您不需要编写代码来掩盖潜在的bug,这才有意义

相反,检查异常(例如
FileNotFoundException
)更可能发生。因此,您要么需要覆盖(捕获)它,要么需要明确说明您没有覆盖它(通过添加
throws
子句)

因此,真正的问题是,
ClassCastException
(或任何其他
reflectiveoperationxeption
)是您应该涵盖的内容


我认为这是有争议的。在过去几年中,关于检查异常的使用有一些讨论。所以目前意见不一。

考虑接受一个答案来结束这个问题,谢谢。。。
java.lang.Object
 java.lang.Throwable
  java.lang.Exception
   java.lang.RuntimeException