Я играю с новыми функциями лямбда в Java 8 и обнаружил, что практика, предлагаемая Java 8, действительно полезна. Тем не менее, мне интересно, есть ли хороший способ сделать обход для следующего сценария. Предположим, у вас есть оболочка пула объектов, для которой требуется некоторый вид factory для заполнения пула объектов, например (с помощью java.lang.functions.Factory
):
public class JdbcConnectionPool extends ObjectPool<Connection> {
public ConnectionPool(int maxConnections, String url) {
super(new Factory<Connection>() {
@Override
public Connection make() {
try {
return DriverManager.getConnection(url);
} catch ( SQLException ex ) {
throw new RuntimeException(ex);
}
}
}, maxConnections);
}
}
После преобразования функционального интерфейса в лямбда-выражение вышеописанный код выглядит следующим образом:
public class JdbcConnectionPool extends ObjectPool<Connection> {
public ConnectionPool(int maxConnections, String url) {
super(() -> {
try {
return DriverManager.getConnection(url);
} catch ( SQLException ex ) {
throw new RuntimeException(ex);
}
}, maxConnections);
}
}
Не так уж и плохо, но проверенное исключение java.sql.SQLException
требует блока try
/catch
внутри лямбда. В моей компании мы используем два интерфейса в течение длительного времени:
-
IOut<T>
, что эквивалентноjava.lang.functions.Factory
; - и специальный интерфейс для случаев, которые обычно требуют проверки распространения исключений:
interface IUnsafeOut<T, E extends Throwable> { T out() throws E; }
.
Обе версии IOut<T>
и IUnsafeOut<T>
должны быть удалены во время перехода на Java 8, однако точное соответствие для IUnsafeOut<T, E>
отсутствует. Если лямбда-выражения могут иметь дело с проверенными исключениями, такими как они были сняты, в конструкторе, описанном выше, можно было бы использовать в качестве следующего:
super(() -> DriverManager.getConnection(url), maxConnections);
Это выглядит намного чище. Я вижу, что я могу переписать суперкласс ObjectPool
, чтобы принять наш IUnsafeOut<T>
, но, насколько я знаю, Java 8 еще не закончена, поэтому могут быть некоторые изменения, например:
- реализация чего-то похожего на
IUnsafeOut<T, E>
? (честно говоря, я считаю это грязным - субъект должен выбрать, что принять: либоFactory
, либо "небезопасный factory", который не может иметь совместимые сигнатуры методов) - просто игнорирует проверенные исключения в lambdas, поэтому нет необходимости в
IUnsafeOut<T, E>
суррогатах? (почему бы и нет? Например, еще одно важное изменение: OpenJDK, который я использую,javac
теперь не требует, чтобы переменные и параметры объявлялись какfinal
для захвата в анонимном классе [функциональный интерфейс] или лямбда-выражение)
Таким образом, обычно возникает вопрос: существует ли способ обойти проверенные исключения в lambdas или планируется ли он в будущем до тех пор, пока Java 8 не будет окончательно выпущен?
Обновление 1
Hm-mm, насколько я понимаю, что у нас сейчас есть, кажется, что на данный момент нет способа, несмотря на то, что ссылочная статья датируется 2010 годом: Брайан Гетц объясняет прозрачность исключений в Java. Если в Java 8 ничего не изменилось, это можно было бы считать ответом. Также Брайан говорит, что interface ExceptionalCallable<V, E extends Exception>
(то, что я упоминал как IUnsafeOut<T, E extends Throwable>
из нашего наследия кода) в значительной степени бесполезно, и я согласен с ним.
Я еще что-то пропустил?