2017-08-14 45 views
1

我想概括出以下模式:的JavaFX:錯誤記錄的ChangeListener

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不是一個Functional接口。

是否有機會將此類轉換爲功能接口?

這並不編譯:

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(); 
    }); 

該錯誤消息是

未處理的異常[..]

+0

沒有意義,您嘗試調用未實現的函數。超級的功能沒有實現,因爲你覆蓋它。你只提供一個界面功能,但試着用它2次... – JohnnyAW

+0

@JohnnyAW同意。如何解決這個問題? – kerner1000

+0

你不可能以你想使用它的方式使用它(至少在java中,也許其他語言可以使用它)。 Waitö讓我想想......使用你的'ErrorLoggingSetChangeListener'的 – JohnnyAW

回答

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) 
+0

我更喜歡這個解決方案,因爲'DangerousInterface'依賴於'SetChangeListener.Change',但似乎一般不會連接到Set或SetChangeListener。這個看起來非常乾淨,謝謝! – kerner1000

1

這裏是我的實現,將編譯:

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(); 
     } 
    } 

} 

DangerousInterface:

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(); 
    }); 

我definitel Y沒有編譯錯誤

編輯:好吧,我得到了這個問題,你需要一個新的界面,實際上可以扔東西,現在你可以用它在onChanged

+0

你聲明瞭你自己的類型'SetChangeListener'。嘗試使用'javafx.collections.SetChangeListener'。 – kerner1000

+0

這個應該沒有區別,但是生病試試,等一下 – JohnnyAW

+0

不同之處在於這個onChange方法並沒有拋出異常;) – kerner1000