从 Java 中的抽象 Runnable.run() 引发异常

发布于 2024-11-03 03:46:10 字数 1342 浏览 4 评论 0原文

我创建了一个抽象线程,在其 run() 方法中处理一些流。我希望能够让子类而不是抽象父类处理这些异常,但我不知道最优雅的方法。现在,我正在做这样的事情:

import org.apache.logging.log4j; // (I use log4j for logging)

public interface Loggable {
     Logger getLogger();
}

public abstract class ParentThread extends Thread implements Loggable {
    private final static Logger logger =
      Logger.getLogger(ParentThread.class); // Logger with no Appenders

    @Override
    public void run() {
        try {
            // Do some stuff that throws exceptions
            doAbstractStuff();
        } catch (SomeSortOfException ex) {
            getLogger().error("Oh noes!", ex);
        } catch (SomeOtherException ex) {
            getLogger().error("The sky is falling!", ex);
        }
    }

    public Logger getLogger() { return logger; }

    protected abstract void doAbstractStuff();
}

public class ChildThread extends ParentThread {

    @Override
    public Logger getLogger() { /* return a logger that I actually use */ }

    @Override
    public void doAbstractStuff() { /* Implementation */ }
}

我想我应该提到 ChildThread 实际上是我的主窗体的内部类,并且它的记录器属于该窗体。

我想到的另一种方法是

abstract void handleException(Exception ex);

在 ParentThread 中使用一个方法,但是这样我就无法处理来自 ChildThread 的单个异常。

I've made an abstract Thread that processes some streams in its run() method. I'd like to be able to have the subclasses handle these exceptions rather than the abstract parent class, but I don't know the most elegant way to do that. Right now, I'm doing something like this:

import org.apache.logging.log4j; // (I use log4j for logging)

public interface Loggable {
     Logger getLogger();
}

public abstract class ParentThread extends Thread implements Loggable {
    private final static Logger logger =
      Logger.getLogger(ParentThread.class); // Logger with no Appenders

    @Override
    public void run() {
        try {
            // Do some stuff that throws exceptions
            doAbstractStuff();
        } catch (SomeSortOfException ex) {
            getLogger().error("Oh noes!", ex);
        } catch (SomeOtherException ex) {
            getLogger().error("The sky is falling!", ex);
        }
    }

    public Logger getLogger() { return logger; }

    protected abstract void doAbstractStuff();
}

public class ChildThread extends ParentThread {

    @Override
    public Logger getLogger() { /* return a logger that I actually use */ }

    @Override
    public void doAbstractStuff() { /* Implementation */ }
}

I guess I should mention that the ChildThread is actually an inner class of my main form, and that its logger belongs to that form.

Another approach I thought of was to have an

abstract void handleException(Exception ex);

in ParentThread, but then I'm not able to handle individual exceptions from the ChildThread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怀里藏娇 2024-11-10 03:46:10

您的第一个解决方案在我看来在概念上是错误的:将特定于应用程序的错误处理与通用日志记录混合在一起。

您的第二个想法(回调)似乎是一个更好的解决方案,并提供了抽象自定义事件的特定于实现的异常的可能性,例如:

public abstract class Parent {

    public void run() {

        InputStream in = null;    
        try {
            in = new URL("bladiebla").openConnection().getInputStream();    
            String text = // ...read text from InputStream     
            if (text == null || text.length() == 0) {
                handleMyEvent(new NoInputEvent());
                return;
            }           
            doWork(text);
        } catch (MalformedURLException e) {
            handleMyEvent(new MyEvent(e));                
        } catch (IOException e) {
            handleMyEvent(new MyEvent(e));
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch(IOException e) {
                    handleMyEvent(e);
                }
            }
        }
    }            

    abstract void doWork(String text);

    abstract void handleMyEvent(MyEvent myEvent);
}

public class MyEvent {
    private Exception exception;
    public MyEvent() {}
    public MyEvent(Exception exception) {//set it}
}

public class NoInputEvent extends MyEvent {        
}

Your first solution seems conceptually wrong to me: mixing application-specific error-handling with generic logging.

Your second idea (the callback) seems a better solution and offers the possibility of abstracting away the implementation-specific exceptions for custom events, for example:

public abstract class Parent {

    public void run() {

        InputStream in = null;    
        try {
            in = new URL("bladiebla").openConnection().getInputStream();    
            String text = // ...read text from InputStream     
            if (text == null || text.length() == 0) {
                handleMyEvent(new NoInputEvent());
                return;
            }           
            doWork(text);
        } catch (MalformedURLException e) {
            handleMyEvent(new MyEvent(e));                
        } catch (IOException e) {
            handleMyEvent(new MyEvent(e));
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch(IOException e) {
                    handleMyEvent(e);
                }
            }
        }
    }            

    abstract void doWork(String text);

    abstract void handleMyEvent(MyEvent myEvent);
}

public class MyEvent {
    private Exception exception;
    public MyEvent() {}
    public MyEvent(Exception exception) {//set it}
}

public class NoInputEvent extends MyEvent {        
}
瑶笙 2024-11-10 03:46:10

两者之间没有区别

} catch (SomeSortOfException ex) {
    getLogger().error("Oh noes!", ex);
} catch (SomeOtherException ex) {
    getLogger().error("The sky is falling!", ex);
}

,但

if (ex instanceof SomeSortOfException) {
    getLogger().error("Oh noes!", ex);
} else if (ex instanceof SomeOtherException) {
    getLogger().error("The sky is falling!", ex);
}

好吧,虽然后者可能需要一些转换

。你的abstracthandleException(Exception ex)想法是合理的,我会同意的。不过,我倾向于使其抽象,并在ParentThread中定义一个合理的默认实现,并允许ChildThread< /code> 如果需要的话可以覆盖它。

Well there's no difference between

} catch (SomeSortOfException ex) {
    getLogger().error("Oh noes!", ex);
} catch (SomeOtherException ex) {
    getLogger().error("The sky is falling!", ex);
}

and

if (ex instanceof SomeSortOfException) {
    getLogger().error("Oh noes!", ex);
} else if (ex instanceof SomeOtherException) {
    getLogger().error("The sky is falling!", ex);
}

although the latter may require some casting.

Your abstract handleException(Exception ex) idea is sound, I'd go with that. I'd be inclined to not make it abstract, though, and define a sensible default implementation in ParentThread, and allow ChildThread to override it if required.

年华零落成诗 2024-11-10 03:46:10

为什么你的基类会记录异常?为什么不使用平台提供的 Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) 并让它做任何事情,而不是将日志记录与您的 do-stuff 组件混合。

Why is your base class logging exceptions ? Why not use what the platform provide Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) and let it do whatever instead of mixing logging w/ your do-stuff component.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文