Don't swallow exceptions
Make sure the exceptions are handled and not swallowed.public void notifyOthers() { try { List<party> interestedParties = fetchInterestedPartiesFromDb(); } catch (Exception e) { // do nothing } } private List<party> fetchInterestedPartiesFromDb() throws Exception { return fetchFromDb(Party.class); } private <t> List<t> fetchFromDb(Class<t> partyClass) { //interact with db return null; }
An exception caught must be logged
Make sure the complete exception is logged rather than just logging the message usingException.getMessage()
.
public void notifyOthers() { try { List<party> interestedParties = fetchInterestedPartiesFromDb(); } catch (Exception e) { LOGGER.severe(e.getMessage()); } }Instead of the above, we should simply log the exception object itself so that one can see the entire execution stack.
public void notifyOthers() { try { List<party> interestedParties = fetchInterestedPartiesFromDb(); } catch (Exception e) { LOGGER.severe("Exception " + e); } }
Do not catch Throwable
If you catchThrowable
even errors will be caught, for example, java.lang.OutOfMemoryError
. Below code throws OutOfMemoryError
but is caught instead of letting JVM deal with it. Since Throwable
is superclass of Error
and Exception
, it will catch even those errors which indicate serious problem.
![]() |
Exception hierarchy |
ThrowsOom:
package refactor.clean; import java.util.logging.Logger; public class ThrowsOom { public static void main(String[] args) { try { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000000; i++) { sb.append(i).append(sb); } } catch (Throwable t) { LOGGER.severe("Throwable: " + t); } LOGGER.warning("Throwable is caught, replace it with Exception"); } private static final Logger LOGGER = Logger.getLogger(ThrowsOom.class.getName()); }
Output:
Jan 16, 2017 5:29:56 PM refactor.clean.ThrowsOom main SEVERE: Throwable: java.lang.OutOfMemoryError: Java heap space Jan 16, 2017 5:29:56 PM refactor.clean.ThrowsOom main WARNING: Throwable is caught, replace it with ExceptionCatch
Exception
instead of Throwable
.
ThrowsOom:
package refactor.clean; import java.util.logging.Logger; public class ThrowsOom { public static void main(String[] args) { try { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000000; i++) { sb.append(i).append(sb); } } catch (Throwable t) { LOGGER.severe("Throwable: " + t); } LOGGER.warning("Throwable is caught, replace it with Exception"); try { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000000; i++) { sb.append(i).append(sb); } } catch (Exception e) { LOGGER.severe("Exception: " + e); } } private static final Logger LOGGER = Logger.getLogger(ThrowsOom.class.getName()); }Output:
Jan 16, 2017 5:55:11 PM refactor.clean.ThrowsOom main SEVERE: Throwable: java.lang.OutOfMemoryError: Java heap space Jan 16, 2017 5:55:11 PM refactor.clean.ThrowsOom main WARNING: Throwable is caught, replace it with Exception Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3332) at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:445) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:459) at java.lang.StringBuilder.append(StringBuilder.java:166) at refactor.clean.ThrowsOom.main(ThrowsOom.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Don't throw generic exception
Below method tries to find an existing issue for the passed in IDissueId
.
If issue not found throws a RuntimeException
.
public static Issue findById(String issueId) throws RuntimeException { Issue issue = fetchFromDb(issueId); if (issue == null) { throw new RuntimeException("Issue not found"); } return issue; }Instead of a generic exception, one can define and throw a dedicated exception.
IssueNotFoundException:
package refactor; public class IssueNotFoundException extends RuntimeException { public IssueNotFoundException(String message) { super(message); } }Fix
findById()
to throw specific exception.
public static Issue findById(String issueId) throws IssueNotFoundException { Issue issue = fetchFromDb(issueId); if (issue == null) { throw new IssueNotFoundException("Issue not found"); } return issue; }Since the method now throws specific exception, the calling methods can handle the exception based on its type. IssueAlreadyResolvedException:
IssueAlreadyResolvedException:
package refactor; public class IssueAlreadyResolvedException extends Exception { public IssueAlreadyResolvedException() { super("Issue already resolved"); } }
public void resolve(String issueId) throws IssueAlreadyResolvedException { Issue issue; try { issue = Issue.findById(issueId); } catch (IssueNotFoundException e) { return; } if (issue.isResolved()) { throw new IssueAlreadyResolvedException(); } issue.resolve(); }
No comments:
Post a Comment