Add ExceptionUtils.asRuntimeException(T), and deprecate rethrow(T)
This commit is contained in:
parent
ce5522f60d
commit
3935fa2f19
|
@ -75,6 +75,7 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add FailableSupplier.nul().</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add Suppliers.nul().</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add ExceptionUtils.throwUnchecked(T) where T extends Throwable, and deprecate Object version.</action>
|
||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add ExceptionUtils.rethrowRuntimeException(T), and deprecate rethrow(T).</action>
|
||||
<!-- UPDATE -->
|
||||
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump commons-parent from 58 to 64.</action>
|
||||
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.easymock:easymock from 5.1.0 to 5.2.0 #1104.</action>
|
||||
|
|
|
@ -71,6 +71,69 @@ public class ExceptionUtils {
|
|||
*/
|
||||
static final String WRAPPED_MARKER = " [wrapped] ";
|
||||
|
||||
/**
|
||||
* Use to throws a checked exception without adding the exception to the throws
|
||||
* clause of the calling method. This method prevents throws clause
|
||||
* pollution and reduces the clutter of "Caused by" exceptions in the
|
||||
* stack trace.
|
||||
* <p>
|
||||
* The use of this technique may be controversial, but exceedingly useful to
|
||||
* library developers.
|
||||
* </p>
|
||||
* <pre>
|
||||
* public int propagateExample { // note that there is no throws clause
|
||||
* try {
|
||||
* return invocation(); // throws IOException
|
||||
* } catch (Exception e) {
|
||||
* return ExceptionUtils.rethrowRuntimeException(e); // propagates a checked exception
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* This is an alternative to the more conservative approach of wrapping the
|
||||
* checked exception in a RuntimeException:
|
||||
* </p>
|
||||
* <pre>
|
||||
* public int wrapExample { // note that there is no throws clause
|
||||
* try {
|
||||
* return invocation(); // throws IOException
|
||||
* } catch (Error e) {
|
||||
* throw e;
|
||||
* } catch (RuntimeException e) {
|
||||
* throw e; // wraps a checked exception
|
||||
* } catch (Exception e) {
|
||||
* throw new UndeclaredThrowableException(e); // wraps a checked exception
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* One downside to using this approach is that the java compiler will not
|
||||
* allow invoking code to specify a checked exception in a catch clause
|
||||
* unless there is some code path within the try block that has invoked a
|
||||
* method declared with that checked exception. If the invoking site wishes
|
||||
* to catch the shaded checked exception, it must either invoke the shaded
|
||||
* code through a method re-declaring the desired checked exception, or
|
||||
* catch Exception and use the instanceof operator. Either of these
|
||||
* techniques are required when interacting with non-java jvm code such as
|
||||
* Jython, Scala, or Groovy, since these languages do not consider any
|
||||
* exceptions as checked.
|
||||
* </p>
|
||||
*
|
||||
* @param throwable
|
||||
* The throwable to rethrow.
|
||||
* @param <T> The type of the returned value.
|
||||
* @return Never actually returned, this generic type matches any type
|
||||
* which the calling site requires. "Returning" the results of this
|
||||
* method, as done in the propagateExample above, will satisfy the
|
||||
* java compiler requirement that all code paths return a value.
|
||||
* @since 3.14.0
|
||||
* @see #wrapAndThrow(Throwable)
|
||||
*/
|
||||
public static <T extends RuntimeException> T asRuntimeException(final Throwable throwable) {
|
||||
// claim that the typeErasure invocation throws a RuntimeException
|
||||
return ExceptionUtils.<T, RuntimeException>eraseType(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Claims a Throwable is another Throwable type using type erasure. This
|
||||
* hides a checked exception from the Java compiler, allowing a checked
|
||||
|
@ -751,7 +814,7 @@ public class ExceptionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Throws a checked exception without adding the exception to the throws
|
||||
* Use to throw a checked exception without adding the exception to the throws
|
||||
* clause of the calling method. This method prevents throws clause
|
||||
* pollution and reduces the clutter of "Caused by" exceptions in the
|
||||
* stack trace.
|
||||
|
@ -800,17 +863,19 @@ public class ExceptionUtils {
|
|||
*
|
||||
* @param throwable
|
||||
* The throwable to rethrow.
|
||||
* @param <R> The type of the returned value.
|
||||
* @param <T> The type of the returned value.
|
||||
* @return Never actually returned, this generic type matches any type
|
||||
* which the calling site requires. "Returning" the results of this
|
||||
* method, as done in the propagateExample above, will satisfy the
|
||||
* java compiler requirement that all code paths return a value.
|
||||
* @since 3.5
|
||||
* @see #wrapAndThrow(Throwable)
|
||||
* @deprecated Use {@link #asRuntimeException(Throwable)}.
|
||||
*/
|
||||
public static <R> R rethrow(final Throwable throwable) {
|
||||
@Deprecated
|
||||
public static <T> T rethrow(final Throwable throwable) {
|
||||
// claim that the typeErasure invocation throws a RuntimeException
|
||||
return ExceptionUtils.<R, RuntimeException>eraseType(throwable);
|
||||
return ExceptionUtils.<T, RuntimeException>eraseType(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -993,11 +1058,8 @@ public class ExceptionUtils {
|
|||
* @since 3.14.0
|
||||
*/
|
||||
public static <T extends Throwable> T throwUnchecked(final T throwable) {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
throw (RuntimeException) throwable;
|
||||
}
|
||||
if (throwable instanceof Error) {
|
||||
throw (Error) throwable;
|
||||
if (isUnchecked(throwable)) {
|
||||
throw asRuntimeException(throwable);
|
||||
}
|
||||
return throwable;
|
||||
}
|
||||
|
@ -1021,7 +1083,7 @@ public class ExceptionUtils {
|
|||
* method will satisfy the java compiler requirement that all code
|
||||
* paths return a value.
|
||||
* @since 3.5
|
||||
* @see #rethrow(Throwable)
|
||||
* @see #asRuntimeException(Throwable)
|
||||
* @see #hasCause(Throwable, Class)
|
||||
*/
|
||||
public static <R> R wrapAndThrow(final Throwable throwable) {
|
||||
|
|
|
@ -585,7 +585,7 @@ public class FastDatePrinter implements DatePrinter, Serializable {
|
|||
rule.appendTo(buf, calendar);
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
ExceptionUtils.rethrow(ioe);
|
||||
ExceptionUtils.asRuntimeException(ioe);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,8 @@ public class ExceptionUtilsTest extends AbstractLangTest {
|
|||
try {
|
||||
throw new IOException();
|
||||
} catch (final Exception e) {
|
||||
return ExceptionUtils.<Integer>rethrow(e);
|
||||
ExceptionUtils.asRuntimeException(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,6 +204,13 @@ public class ExceptionUtilsTest extends AbstractLangTest {
|
|||
assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsRuntimeException() {
|
||||
final Exception expected = new InterruptedException();
|
||||
final Exception actual = assertThrows(Exception.class, () -> ExceptionUtils.asRuntimeException(expected));
|
||||
assertSame(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCatchTechniques() {
|
||||
IOException ioe = assertThrows(IOException.class, ExceptionUtilsTest::throwsCheckedException);
|
||||
|
@ -765,7 +773,7 @@ public class ExceptionUtilsTest extends AbstractLangTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testThrow() {
|
||||
public void testRethrow() {
|
||||
final Exception expected = new InterruptedException();
|
||||
final Exception actual = assertThrows(Exception.class, () -> ExceptionUtils.rethrow(expected));
|
||||
assertSame(expected, actual);
|
||||
|
|
Loading…
Reference in New Issue