簡體   English   中英

在 lambda 內拋出異常不起作用

[英]Throwing exception inside lambda does not work

我在 lambda 中拋出異常時遇到了一些問題,請考慮以下代碼:

public interface StoreTransactionalExecutable {
    void execute(@NotNull final StoreTransaction txn);
}

還有一個經理 class:

public final class DatabaseManager {
  // ...
  @Override
  public void transactPersistentEntityStore(String dir, StoreTransactionalExecutable txn) {
    final PersistentEntityStore entityStore =
        getPersistentEntityStore(dir, isReadOnly);
    entityStore.executeInTransaction(txn);
  }
  // ...
}

當像下面這樣訪問管理器 class 方法transactPersistentEntityStore時,它可以工作:

public class Service {
    databaseManager.transactPersistentEntityStore("/dbPath", txn -> {
         txn.find(); // do stuff (throws and works)
    });
}

但是,如果這樣,它會引發編譯時錯誤

public class Service {
    databaseManager.transactPersistentEntityStore("/dbPath", rethrow(
        transaction -> {
            StoreTransaction txn = (StoreTransaction) transaction; 
            txn.find(); // do stuff 
        }
     ));
}

這是扔的東西

[ERROR]     method com.myproject.store.DatabaseManager.transactPersistentEntityStore(java.lang.String,jetbrains.exodus.entitystore.StoreTransactionalExecutable) is not applicable
[ERROR]       (argument mismatch; no instance(s) of type variable(s) T exist so that java.util.function.Consumer<T> conforms to jetbrains.exodus.entitystore.StoreTransactionalExecutable)
[ERROR]     method com.myproject.store.DatabaseManager.<T,B>transactPersistentEntityStore(java.lang.String,java.util.Map<java.lang.Class<T>,B>,jetbrains.exodus.entitystore.StoreTransactionalExecutable) is not applicable
[ERROR]       (cannot infer type-variable(s) T,B
[ERROR]         (actual and formal argument lists differ in length))

rethrowThrowingConsumer的代碼是這樣的:

public final class Throwing {

  private Throwing() {}

  @Nonnull
  public static <T> Consumer<T> rethrow(@Nonnull final ThrowingConsumer<T> consumer) {
    return consumer;
  }

  @SuppressWarnings("unchecked")
  @Nonnull
  public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
    throw (E) ex;
  }

}

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T>{
  @Override
  default void accept(final T e) {
    try {
      accept0(e);
    } catch (Throwable ex) {
      Throwing.sneakyThrow(ex);
    }
  }
  void accept0(T t) throws Throwable;
}

我真的很想知道這里有什么問題? 任何提示將不勝感激。

關於第一個編譯器錯誤:
如果您仔細閱讀錯誤“參數不匹配;不存在類型變量 T 的實例,因此 java.util.function.Consumer 符合 jetbrains.exodus.entitystore.Sto reTransactionalExecutable”
你會注意到一些事情:

  1. StoreTransactionalExecutable 與 Consumer 不同。
  2. StoreTransactionalExecutable 不是泛型類型。 而消費者是。
  3. StoreTransactionalExecutable 不擴展消費者並且具有execute方法 not accept 所以在entityStore.executeInTransaction(txn);里面的代碼調用execute方法而不accept

因此,當您將 Consumer object 傳遞給transactPersistentEntityStore方法時,編譯器會抱怨。
如果我錯了,請糾正我。

一種“偷偷摸摸”的方式來拋出這個(但有一個try-catch)是做一個:

public class UncheckedException extends RuntimeException {
  public UncheckedException(Throwable cause) {
    super(cause);
  }
}

然后像這樣使用:

class Scratch {
    public static void main(String[] args) {
        databaseManager.transactPersistentEntityStore("/dbPath", txn -> {
            try {
                somethingThatThrows();
            } catch (Exception e) {
                throw new UnchecekdServiceException(e);
            }
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM