001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.io.IOException; 020import java.io.UncheckedIOException; 021import java.lang.reflect.UndeclaredThrowableException; 022import java.util.Collection; 023import java.util.Objects; 024import java.util.concurrent.Callable; 025import java.util.function.BiConsumer; 026import java.util.function.BiFunction; 027import java.util.function.BiPredicate; 028import java.util.function.Consumer; 029import java.util.function.Function; 030import java.util.function.Predicate; 031import java.util.function.Supplier; 032import java.util.stream.Stream; 033 034import org.apache.commons.lang3.Streams.FailableStream; 035import org.apache.commons.lang3.function.FailableBooleanSupplier; 036 037/** 038 * This class provides utility functions, and classes for working with the {@code java.util.function} package, or more 039 * generally, with Java 8 lambdas. More specifically, it attempts to address the fact that lambdas are supposed not to 040 * throw Exceptions, at least not checked Exceptions, AKA instances of {@link Exception}. This enforces the use of 041 * constructs like: 042 * 043 * <pre> 044 * {@code 045 * Consumer<java.lang.reflect.Method> consumer = (m) -> { 046 * try { 047 * m.invoke(o, args); 048 * } catch (Throwable t) { 049 * throw Functions.rethrow(t); 050 * } 051 * }; 052 * }</pre> 053 * 054 * <p> 055 * By replacing a {@link java.util.function.Consumer Consumer<O>} with a {@link FailableConsumer 056 * FailableConsumer<O,? extends Throwable>}, this can be written like follows: 057 * </p> 058 * 059 * <pre> 060 * {@code 061 * Functions.accept((m) -> m.invoke(o,args)); 062 * }</pre> 063 * 064 * <p> 065 * Obviously, the second version is much more concise and the spirit of Lambda expressions is met better than the second 066 * version. 067 * </p> 068 * @since 3.9 069 * @deprecated Use {@link org.apache.commons.lang3.function.Failable}. 070 */ 071@Deprecated 072public class Functions { 073 074 /** 075 * A functional interface like {@link BiConsumer} that declares a {@code Throwable}. 076 * 077 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 078 * 079 * @param <O1> Consumed type 1. 080 * @param <O2> Consumed type 2. 081 * @param <T> Thrown exception. 082 * @deprecated Use {@link org.apache.commons.lang3.function.FailableBiConsumer}. 083 */ 084 @Deprecated 085 @FunctionalInterface 086 public interface FailableBiConsumer<O1, O2, T extends Throwable> { 087 088 /** 089 * Accepts the consumer. 090 * 091 * @param object1 the first parameter for the consumable to accept 092 * @param object2 the second parameter for the consumable to accept 093 * @throws T Thrown when the consumer fails. 094 */ 095 void accept(O1 object1, O2 object2) throws T; 096 } 097 098 /** 099 * A functional interface like {@link BiFunction} that declares a {@code Throwable}. 100 * 101 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 102 * 103 * @param <O1> Input type 1. 104 * @param <O2> Input type 2. 105 * @param <R> Return type. 106 * @param <T> Thrown exception. 107 * @deprecated Use {@link org.apache.commons.lang3.function.FailableBiFunction}. 108 */ 109 @Deprecated 110 @FunctionalInterface 111 public interface FailableBiFunction<O1, O2, R, T extends Throwable> { 112 113 /** 114 * Applies this function. 115 * 116 * @param input1 the first input for the function 117 * @param input2 the second input for the function 118 * @return the result of the function 119 * @throws T Thrown when the function fails. 120 */ 121 R apply(O1 input1, O2 input2) throws T; 122 } 123 124 /** 125 * A functional interface like {@link BiPredicate} that declares a {@code Throwable}. 126 * 127 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 128 * 129 * @param <O1> Predicate type 1. 130 * @param <O2> Predicate type 2. 131 * @param <T> Thrown exception. 132 * @deprecated Use {@link org.apache.commons.lang3.function.FailableBiPredicate}. 133 */ 134 @Deprecated 135 @FunctionalInterface 136 public interface FailableBiPredicate<O1, O2, T extends Throwable> { 137 138 /** 139 * Tests the predicate. 140 * 141 * @param object1 the first object to test the predicate on 142 * @param object2 the second object to test the predicate on 143 * @return the predicate's evaluation 144 * @throws T if the predicate fails 145 */ 146 boolean test(O1 object1, O2 object2) throws T; 147 } 148 149 /** 150 * A functional interface like {@link java.util.concurrent.Callable} that declares a {@code Throwable}. 151 * 152 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 153 * 154 * @param <R> Return type. 155 * @param <T> Thrown exception. 156 * @deprecated Use {@link org.apache.commons.lang3.function.FailableCallable}. 157 */ 158 @Deprecated 159 @FunctionalInterface 160 public interface FailableCallable<R, T extends Throwable> { 161 162 /** 163 * Calls the callable. 164 * 165 * @return The value returned from the callable 166 * @throws T if the callable fails 167 */ 168 R call() throws T; 169 } 170 171 /** 172 * A functional interface like {@link Consumer} that declares a {@code Throwable}. 173 * 174 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 175 * 176 * @param <O> Consumed type 1. 177 * @param <T> Thrown exception. 178 * @deprecated Use {@link org.apache.commons.lang3.function.FailableConsumer}. 179 */ 180 @Deprecated 181 @FunctionalInterface 182 public interface FailableConsumer<O, T extends Throwable> { 183 184 /** 185 * Accepts the consumer. 186 * 187 * @param object the parameter for the consumable to accept 188 * @throws T Thrown when the consumer fails. 189 */ 190 void accept(O object) throws T; 191 } 192 193 /** 194 * A functional interface like {@link Function} that declares a {@code Throwable}. 195 * 196 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 197 * 198 * @param <I> Input type 1. 199 * @param <R> Return type. 200 * @param <T> Thrown exception. 201 * @deprecated Use {@link org.apache.commons.lang3.function.FailableFunction}. 202 */ 203 @Deprecated 204 @FunctionalInterface 205 public interface FailableFunction<I, R, T extends Throwable> { 206 207 /** 208 * Applies this function. 209 * 210 * @param input the input for the function 211 * @return the result of the function 212 * @throws T Thrown when the function fails. 213 */ 214 R apply(I input) throws T; 215 } 216 217 /** 218 * A functional interface like {@link Predicate} that declares a {@code Throwable}. 219 * 220 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 221 * 222 * @param <I> Predicate type 1. 223 * @param <T> Thrown exception. 224 * @deprecated Use {@link org.apache.commons.lang3.function.FailablePredicate}. 225 */ 226 @Deprecated 227 @FunctionalInterface 228 public interface FailablePredicate<I, T extends Throwable> { 229 230 /** 231 * Tests the predicate. 232 * 233 * @param object the object to test the predicate on 234 * @return the predicate's evaluation 235 * @throws T if the predicate fails 236 */ 237 boolean test(I object) throws T; 238 } 239 240 /** 241 * A functional interface like {@link Runnable} that declares a {@code Throwable}. 242 * 243 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 244 * 245 * @param <T> Thrown exception. 246 * @deprecated Use {@link org.apache.commons.lang3.function.FailableRunnable}. 247 */ 248 @Deprecated 249 @FunctionalInterface 250 public interface FailableRunnable<T extends Throwable> { 251 252 /** 253 * Runs the function. 254 * 255 * @throws T Thrown when the function fails. 256 */ 257 void run() throws T; 258 } 259 260 /** 261 * A functional interface like {@link Supplier} that declares a {@code Throwable}. 262 * 263 * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p> 264 * 265 * @param <R> Return type. 266 * @param <T> Thrown exception. 267 * @deprecated Use {@link org.apache.commons.lang3.function.FailableSupplier}. 268 */ 269 @Deprecated 270 @FunctionalInterface 271 public interface FailableSupplier<R, T extends Throwable> { 272 273 /** 274 * Supplies an object 275 * 276 * @return a result 277 * @throws T if the supplier fails 278 */ 279 R get() throws T; 280 } 281 282 /** 283 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}. 284 * 285 * @param consumer the consumer to consume 286 * @param object1 the first object to consume by {@code consumer} 287 * @param object2 the second object to consume by {@code consumer} 288 * @param <O1> the type of the first argument the consumer accepts 289 * @param <O2> the type of the second argument the consumer accepts 290 * @param <T> the type of checked exception the consumer may throw 291 */ 292 public static <O1, O2, T extends Throwable> void accept(final FailableBiConsumer<O1, O2, T> consumer, 293 final O1 object1, final O2 object2) { 294 run(() -> consumer.accept(object1, object2)); 295 } 296 297 /** 298 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}. 299 * 300 * @param consumer the consumer to consume 301 * @param object the object to consume by {@code consumer} 302 * @param <O> the type the consumer accepts 303 * @param <T> the type of checked exception the consumer may throw 304 */ 305 public static <O, T extends Throwable> void accept(final FailableConsumer<O, T> consumer, final O object) { 306 run(() -> consumer.accept(object)); 307 } 308 309 /** 310 * Applies a function and rethrows any exception as a {@link RuntimeException}. 311 * 312 * @param function the function to apply 313 * @param input1 the first input to apply {@code function} on 314 * @param input2 the second input to apply {@code function} on 315 * @param <O1> the type of the first argument the function accepts 316 * @param <O2> the type of the second argument the function accepts 317 * @param <O> the return type of the function 318 * @param <T> the type of checked exception the function may throw 319 * @return the value returned from the function 320 */ 321 public static <O1, O2, O, T extends Throwable> O apply(final FailableBiFunction<O1, O2, O, T> function, 322 final O1 input1, final O2 input2) { 323 return get(() -> function.apply(input1, input2)); 324 } 325 326 /** 327 * Applies a function and rethrows any exception as a {@link RuntimeException}. 328 * 329 * @param function the function to apply 330 * @param input the input to apply {@code function} on 331 * @param <I> the type of the argument the function accepts 332 * @param <O> the return type of the function 333 * @param <T> the type of checked exception the function may throw 334 * @return the value returned from the function 335 */ 336 public static <I, O, T extends Throwable> O apply(final FailableFunction<I, O, T> function, final I input) { 337 return get(() -> function.apply(input)); 338 } 339 340 /** 341 * Converts the given {@link FailableBiConsumer} into a standard {@link BiConsumer}. 342 * 343 * @param <O1> the type of the first argument of the consumers 344 * @param <O2> the type of the second argument of the consumers 345 * @param consumer a failable {@code BiConsumer} 346 * @return a standard {@code BiConsumer} 347 * @since 3.10 348 */ 349 public static <O1, O2> BiConsumer<O1, O2> asBiConsumer(final FailableBiConsumer<O1, O2, ?> consumer) { 350 return (input1, input2) -> accept(consumer, input1, input2); 351 } 352 353 /** 354 * Converts the given {@link FailableBiFunction} into a standard {@link BiFunction}. 355 * 356 * @param <O1> the type of the first argument of the input of the functions 357 * @param <O2> the type of the second argument of the input of the functions 358 * @param <O> the type of the output of the functions 359 * @param function a {@code FailableBiFunction} 360 * @return a standard {@code BiFunction} 361 * @since 3.10 362 */ 363 public static <O1, O2, O> BiFunction<O1, O2, O> asBiFunction(final FailableBiFunction<O1, O2, O, ?> function) { 364 return (input1, input2) -> apply(function, input1, input2); 365 } 366 367 /** 368 * Converts the given {@link FailableBiPredicate} into a standard {@link BiPredicate}. 369 * 370 * @param <O1> the type of the first argument used by the predicates 371 * @param <O2> the type of the second argument used by the predicates 372 * @param predicate a {@code FailableBiPredicate} 373 * @return a standard {@code BiPredicate} 374 * @since 3.10 375 */ 376 public static <O1, O2> BiPredicate<O1, O2> asBiPredicate(final FailableBiPredicate<O1, O2, ?> predicate) { 377 return (input1, input2) -> test(predicate, input1, input2); 378 } 379 380 /** 381 * Converts the given {@link FailableCallable} into a standard {@link Callable}. 382 * 383 * @param <O> the type used by the callables 384 * @param callable a {@code FailableCallable} 385 * @return a standard {@code Callable} 386 * @since 3.10 387 */ 388 public static <O> Callable<O> asCallable(final FailableCallable<O, ?> callable) { 389 return () -> call(callable); 390 } 391 392 /** 393 * Converts the given {@link FailableConsumer} into a standard {@link Consumer}. 394 * 395 * @param <I> the type used by the consumers 396 * @param consumer a {@code FailableConsumer} 397 * @return a standard {@code Consumer} 398 * @since 3.10 399 */ 400 public static <I> Consumer<I> asConsumer(final FailableConsumer<I, ?> consumer) { 401 return input -> accept(consumer, input); 402 } 403 404 /** 405 * Converts the given {@link FailableFunction} into a standard {@link Function}. 406 * 407 * @param <I> the type of the input of the functions 408 * @param <O> the type of the output of the functions 409 * @param function a {code FailableFunction} 410 * @return a standard {@code Function} 411 * @since 3.10 412 */ 413 public static <I, O> Function<I, O> asFunction(final FailableFunction<I, O, ?> function) { 414 return input -> apply(function, input); 415 } 416 417 /** 418 * Converts the given {@link FailablePredicate} into a standard {@link Predicate}. 419 * 420 * @param <I> the type used by the predicates 421 * @param predicate a {@code FailablePredicate} 422 * @return a standard {@code Predicate} 423 * @since 3.10 424 */ 425 public static <I> Predicate<I> asPredicate(final FailablePredicate<I, ?> predicate) { 426 return input -> test(predicate, input); 427 } 428 429 /** 430 * Converts the given {@link FailableRunnable} into a standard {@link Runnable}. 431 * 432 * @param runnable a {@code FailableRunnable} 433 * @return a standard {@code Runnable} 434 * @since 3.10 435 */ 436 public static Runnable asRunnable(final FailableRunnable<?> runnable) { 437 return () -> run(runnable); 438 } 439 440 /** 441 * Converts the given {@link FailableSupplier} into a standard {@link Supplier}. 442 * 443 * @param <O> the type supplied by the suppliers 444 * @param supplier a {@code FailableSupplier} 445 * @return a standard {@code Supplier} 446 * @since 3.10 447 */ 448 public static <O> Supplier<O> asSupplier(final FailableSupplier<O, ?> supplier) { 449 return () -> get(supplier); 450 } 451 452 /** 453 * Calls a callable and rethrows any exception as a {@link RuntimeException}. 454 * 455 * @param callable the callable to call 456 * @param <O> the return type of the callable 457 * @param <T> the type of checked exception the callable may throw 458 * @return the value returned from the callable 459 */ 460 public static <O, T extends Throwable> O call(final FailableCallable<O, T> callable) { 461 return get(callable::call); 462 } 463 464 /** 465 * Invokes a supplier, and returns the result. 466 * 467 * @param supplier The supplier to invoke. 468 * @param <O> The suppliers output type. 469 * @param <T> The type of checked exception, which the supplier can throw. 470 * @return The object, which has been created by the supplier 471 * @since 3.10 472 */ 473 public static <O, T extends Throwable> O get(final FailableSupplier<O, T> supplier) { 474 try { 475 return supplier.get(); 476 } catch (final Throwable t) { 477 throw rethrow(t); 478 } 479 } 480 481 /** 482 * Invokes a boolean supplier, and returns the result. 483 * 484 * @param supplier The boolean supplier to invoke. 485 * @param <T> The type of checked exception, which the supplier can throw. 486 * @return The boolean, which has been created by the supplier 487 */ 488 private static <T extends Throwable> boolean getAsBoolean(final FailableBooleanSupplier<T> supplier) { 489 try { 490 return supplier.getAsBoolean(); 491 } catch (final Throwable t) { 492 throw rethrow(t); 493 } 494 } 495 496 /** 497 * <p> 498 * Rethrows a {@link Throwable} as an unchecked exception. If the argument is already unchecked, namely a 499 * {@code RuntimeException} or {@code Error} then the argument will be rethrown without modification. If the 500 * exception is {@code IOException} then it will be wrapped into a {@code UncheckedIOException}. In every other 501 * cases the exception will be wrapped into a {@code 502 * UndeclaredThrowableException} 503 * </p> 504 * 505 * <p> 506 * Note that there is a declared return type for this method, even though it never returns. The reason for that is 507 * to support the usual pattern: 508 * </p> 509 * 510 * <pre> 511 * throw rethrow(myUncheckedException);</pre> 512 * 513 * <p> 514 * instead of just calling the method. This pattern may help the Java compiler to recognize that at that point an 515 * exception will be thrown and the code flow analysis will not demand otherwise mandatory commands that could 516 * follow the method call, like a {@code return} statement from a value returning method. 517 * </p> 518 * 519 * @param throwable The throwable to rethrow ossibly wrapped into an unchecked exception 520 * @return Never returns anything, this method never terminates normally. 521 */ 522 public static RuntimeException rethrow(final Throwable throwable) { 523 Objects.requireNonNull(throwable, "throwable"); 524 if (throwable instanceof RuntimeException) { 525 throw (RuntimeException) throwable; 526 } else if (throwable instanceof Error) { 527 throw (Error) throwable; 528 } else if (throwable instanceof IOException) { 529 throw new UncheckedIOException((IOException) throwable); 530 } else { 531 throw new UndeclaredThrowableException(throwable); 532 } 533 } 534 535 /** 536 * Runs a runnable and rethrows any exception as a {@link RuntimeException}. 537 * 538 * @param runnable The runnable to run 539 * @param <T> the type of checked exception the runnable may throw 540 */ 541 public static <T extends Throwable> void run(final FailableRunnable<T> runnable) { 542 try { 543 runnable.run(); 544 } catch (final Throwable t) { 545 throw rethrow(t); 546 } 547 } 548 549 /** 550 * Converts the given collection into a {@link FailableStream}. The {@link FailableStream} consists of the 551 * collections elements. Shortcut for 552 * 553 * <pre> 554 * Functions.stream(collection.stream());</pre> 555 * 556 * @param collection The collection, which is being converted into a {@link FailableStream}. 557 * @param <O> The collections element type. (In turn, the result streams element type.) 558 * @return The created {@link FailableStream}. 559 * @since 3.10 560 */ 561 public static <O> FailableStream<O> stream(final Collection<O> collection) { 562 return new FailableStream<>(collection.stream()); 563 } 564 565 /** 566 * Converts the given stream into a {@link FailableStream}. The {@link FailableStream} consists of the same 567 * elements, than the input stream. However, failable lambdas, like {@link FailablePredicate}, 568 * {@link FailableFunction}, and {@link FailableConsumer} may be applied, rather than {@link Predicate}, 569 * {@link Function}, {@link Consumer}, etc. 570 * 571 * @param stream The stream, which is being converted into a {@link FailableStream}. 572 * @param <O> The streams element type. 573 * @return The created {@link FailableStream}. 574 * @since 3.10 575 */ 576 public static <O> FailableStream<O> stream(final Stream<O> stream) { 577 return new FailableStream<>(stream); 578 } 579 580 /** 581 * Tests a predicate and rethrows any exception as a {@link RuntimeException}. 582 * 583 * @param predicate the predicate to test 584 * @param object1 the first input to test by {@code predicate} 585 * @param object2 the second input to test by {@code predicate} 586 * @param <O1> the type of the first argument the predicate tests 587 * @param <O2> the type of the second argument the predicate tests 588 * @param <T> the type of checked exception the predicate may throw 589 * @return the boolean value returned by the predicate 590 */ 591 public static <O1, O2, T extends Throwable> boolean test(final FailableBiPredicate<O1, O2, T> predicate, 592 final O1 object1, final O2 object2) { 593 return getAsBoolean(() -> predicate.test(object1, object2)); 594 } 595 596 /** 597 * Tests a predicate and rethrows any exception as a {@link RuntimeException}. 598 * 599 * @param predicate the predicate to test 600 * @param object the input to test by {@code predicate} 601 * @param <O> the type of argument the predicate tests 602 * @param <T> the type of checked exception the predicate may throw 603 * @return the boolean value returned by the predicate 604 */ 605 public static <O, T extends Throwable> boolean test(final FailablePredicate<O, T> predicate, final O object) { 606 return getAsBoolean(() -> predicate.test(object)); 607 } 608 609 /** 610 * A simple try-with-resources implementation, that can be used, if your objects do not implement the 611 * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em> 612 * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure. 613 * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA 614 * {@link Throwable} is rethrown. Example use: 615 * 616 * <pre> 617 * {@code 618 * final FileInputStream fis = new FileInputStream("my.file"); 619 * Functions.tryWithResources(useInputStream(fis), null, () -> fis.close()); 620 * }</pre> 621 * 622 * @param action The action to execute. This object <em>will</em> always be invoked. 623 * @param errorHandler An optional error handler, which will be invoked finally, if any error occurred. The error 624 * handler will receive the first error, AKA {@link Throwable}. 625 * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given 626 * order. A resource action is an instance of {@link FailableRunnable}, which will be executed. 627 * @see #tryWithResources(FailableRunnable, FailableRunnable...) 628 */ 629 @SafeVarargs 630 public static void tryWithResources(final FailableRunnable<? extends Throwable> action, 631 final FailableConsumer<Throwable, ? extends Throwable> errorHandler, 632 final FailableRunnable<? extends Throwable>... resources) { 633 final FailableConsumer<Throwable, ? extends Throwable> actualErrorHandler; 634 if (errorHandler == null) { 635 actualErrorHandler = Functions::rethrow; 636 } else { 637 actualErrorHandler = errorHandler; 638 } 639 if (resources != null) { 640 for (final FailableRunnable<? extends Throwable> failableRunnable : resources) { 641 Objects.requireNonNull(failableRunnable, "runnable"); 642 } 643 } 644 Throwable th = null; 645 try { 646 action.run(); 647 } catch (final Throwable t) { 648 th = t; 649 } 650 if (resources != null) { 651 for (final FailableRunnable<?> runnable : resources) { 652 try { 653 runnable.run(); 654 } catch (final Throwable t) { 655 if (th == null) { 656 th = t; 657 } 658 } 659 } 660 } 661 if (th != null) { 662 try { 663 actualErrorHandler.accept(th); 664 } catch (final Throwable t) { 665 throw rethrow(t); 666 } 667 } 668 } 669 670 /** 671 * A simple try-with-resources implementation, that can be used, if your objects do not implement the 672 * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em> 673 * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure. 674 * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA 675 * {@link Throwable} is rethrown. Example use: 676 * 677 * <pre> 678 * {@code 679 * final FileInputStream fis = new FileInputStream("my.file"); 680 * Functions.tryWithResources(useInputStream(fis), () -> fis.close()); 681 * }</pre> 682 * 683 * @param action The action to execute. This object <em>will</em> always be invoked. 684 * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given 685 * order. A resource action is an instance of {@link FailableRunnable}, which will be executed. 686 * @see #tryWithResources(FailableRunnable, FailableConsumer, FailableRunnable...) 687 */ 688 @SafeVarargs 689 public static void tryWithResources(final FailableRunnable<? extends Throwable> action, 690 final FailableRunnable<? extends Throwable>... resources) { 691 tryWithResources(action, null, resources); 692 } 693}