【问题标题】:JavaFX: Error-logging ChangeListenerJavaFX:错误记录 ChangeListener
【发布时间】:2017-08-14 09:51:59
【问题描述】:

我想概括以下模式:

setChangeListener = c -> {
    try {
    // do something dangerous
    } catch (final IOException e) {
    logger.error(e.getLocalizedMessage(), e);
    }
};

我想这样使用它:

errorLoggingSetChangeListener = c -> {
    // do something dangerous
};

我在想这个:

public class ErrorLoggingSetChangeListener<T> implements SetChangeListener<T> {
    private static final Logger logger = Logger.getLogger(ErrorLoggingSetChangeListener.class);
    private final SetChangeListener<T> delegate;

    @Override
    public void onChanged(final SetChangeListener.Change<? extends T> change) {
    try {
        delegate.onChanged(change);
    } catch (final Exception e) {
        if (logger.isEnabledFor(Level.ERROR)) {
        logger.error(e.getLocalizedMessage(), e);
        }
    }
    }

    public ErrorLoggingSetChangeListener(final SetChangeListener<T> delegate) {
    super();
    this.delegate = delegate;
    }
}

但这是不可能的,因为 ErrorLoggingSetChangeListener 不是函数式接口。

有没有机会将此类转换为功能接口?

这不会编译:

public interface ErrorLoggingSetChangeListener<T> extends SetChangeListener<T> {

    static final Logger logger = Logger.getLogger(ErrorLoggingSetChangeListener.class);

    @Override
    default void onChanged(final SetChangeListener.Change<? extends T> change) {
    try {
        SetChangeListener.super.onChanged(change);
    } catch (final Exception e) {
        if (logger.isEnabledFor(Level.ERROR)) {
        logger.error(e.getLocalizedMessage(), e);
        }
    }
    }
}

这也不编译:

errorLoggingSetChangeListener = new ErrorLoggingSetChangeListener<>(c -> {
      throw new IOException();
    });

错误信息是

未处理的异常 [..]

.

【问题讨论】:

  • 这没有意义,您尝试调用未实现的函数。 super 的功能没有实现,因为你覆盖了它。你只为接口提供了1个功能,但尝试使用它2次...
  • @JohnnyAW 同意了。如何解决这个问题?
  • 你无法以你想要的方式使用它(至少在java中,也许其他语言可以做到)。 Waitö 让我想想……
  • 使用您的ErrorLoggingSetChangeListener,您可以按如下方式使用它:errorLoggingSetChangeListener = new ErrorLoggingSetChangeListener(c -&gt; {// do something dangerous});。我认为这是您可以使用它的唯一方法...
  • 也不编译,请参阅更新后的问题。

标签: java oop javafx lambda


【解决方案1】:

这类似于@JonnyAW 的解决方案,但将两个类合并到一个接口中:

import javafx.collections.SetChangeListener;

@FunctionalInterface
public interface ErrorLoggingSetChangeListener<E> extends SetChangeListener<E> {


    public void delegate(Change<? extends E> change) throws Exception ;

    @Override
    public default void onChanged(Change<? extends E> change) {
        try {
            delegate(change);
        } catch (Exception exc) {
            // just do a System.out.println here to demo we reach this block:
            System.out.println("Custom error handling...");
            exc.printStackTrace();
        }
    }
}

这是一个使用这个的演示:

import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;

public class Test {

    public static void main(String[] args) {
        ObservableSet<String> set = FXCollections.observableSet();
        ErrorLoggingSetChangeListener<String> listener = c -> {
            if (c.wasAdded()) {
                int i = Integer.parseInt(c.getElementAdded());
                System.out.println("Value added: "+i);
            }
        };
        set.addListener(listener);

        set.add("42");
        set.add("What do you get when you multiply 6 by 9?");
    }

}

产生预期的输出:

Value added: 42
Custom error handling...
java.lang.NumberFormatException: For input string: "What do you get when you multiply 6 by 9?"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.parseInt(Integer.java:615)
    at Test.lambda$0(Test.java:10)
    at ErrorLoggingSetChangeListener.onChanged(ErrorLoggingSetChangeListener.java:12)
    at com.sun.javafx.collections.SetListenerHelper$SingleChange.fireValueChangedEvent(SetListenerHelper.java:163)
    at com.sun.javafx.collections.SetListenerHelper.fireValueChangedEvent(SetListenerHelper.java:72)
    at com.sun.javafx.collections.ObservableSetWrapper.callObservers(ObservableSetWrapper.java:128)
    at com.sun.javafx.collections.ObservableSetWrapper.add(ObservableSetWrapper.java:269)
    at Test.main(Test.java:17)

【讨论】:

  • 我更喜欢这个解决方案,因为 DangerousInterface 依赖于 SetChangeListener.Change 但似乎没有连接到 Set 或一般的 SetChangeListener。这个看起来很干净,谢谢!
【解决方案2】:

这是我的实现,将编译:

ErrorLoggingSetChangeListener:

import javafx.collections.SetChangeListener;

public class ErrorLoggingSetChangeListener<T> implements SetChangeListener<T> {

    private DangerousInterface<T> delegate;

    public ErrorLoggingSetChangeListener(DangerousInterface<T> delegate) {
        super();
        this.delegate = delegate;
    }

    @Override
    public void onChanged(Change<? extends T> change) {
        try {
            this.delegate.delegate(change);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

危险界面:

public interface DangerousInterface<T> {

    public void delegate(Change<? extends T> change) throws Exception;
}

主要:

SetChangeListener<String> listener = new ErrorLoggingSetChangeListener<>((test) -> {
        //no errors here now
        throw new Exception();
    });

我绝对没有编译错误

编辑:好的,我遇到了问题,你需要一个可以实际抛出一些东西的新接口,现在你可以将它包装在 onChanged

【讨论】:

  • 您声明了自己的类型SetChangeListener。尝试使用javafx.collections.SetChangeListener
  • 这应该没什么区别,但是我试试,等一下
  • 不同的是这个onChange方法不会抛出异常;)
  • 就像我说的,没有区别,对我来说没有错误。您可以在当前状态下发布您的代码吗?
  • 等一下,你的记录器会不会扔东西?
猜你喜欢
  • 2020-10-18
  • 2017-05-10
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
相关资源
最近更新 更多