What's better between several ChildException catch blocks and one Exception catch block? By better, I mean in a good-practices way.
To illustrate:
public static void main(String[] args) {
System.out.println(Main.isNonsense1(null)); // false <- bad
System.out.println(Main.isNonsense2(null)); // NullPointerException <- good
}
// More readable, less precise
public static boolean isNonsense1(String className) {
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (Exception e) {
return false;
}
}
// Less readable, more precise
public static boolean isNonsense2(String className) {
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (ClassNotFoundException e) {
return false;
} catch (NoSuchMethodException e) {
return false;
} catch (SecurityException e) {
return false;
} catch (UnsupportedEncodingException e) {
return false;
} catch (NoSuchAlgorithmException e) {
return false;
} catch (InterruptedException e) {
return false;
}
}
This is related to this question: Catch multiple exceptions at once?
The answer there is good. The key is that if you catch Exception then you should handle each of the cases that you are aware of and throw all the rest. That is, simply catching Exception in your example and returning false would not be a good idea. You may inadvertently catch some exception you didn't mean to.
Using your example, here is my suggested code:
public static boolean isNonsense2(String className) {
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (Exception e) {
if (e instanceof ClassNotFoundException
|| e instanceof NoSuchMethodException
|| e instanceof SecurityException
|| e instanceof UnsupportedEncodingException
|| e instanceof NoSuchAlgorithmException
|| e instanceof InterruptedException) {
return false;
} else {
throw e;
}
}
}
I think there is no complete clear answer. In your case I would code it like this:
public static boolean isNonsense1(String className) {
if(slassname==null) throw new IllegalArgumentException("className must not be null");
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("provided class " + className + " not found");
} catch (Exception e) {
return false;
}
}
For my flavor, throwing a NullPointerException is always bad, thats why I throw the IllegalArgumentException
If you are not interested in handling the exception (which you should as per best practices) don't bother with the explicit catches. The whole point of being able to handle specific exceptions is to enable you to handle them correctly.
Related
I have functions with the same param and response type like;
public ResponseType functionA(ParamType) throws Exception1
public ResponseType functionB(ParamType) throws Exception1
and I call these functions from different places with the same repeating try/catch block. Is there any way to reduce the duplicate code?
try{
return functionA(obj);
} catch (Exception1 e) { .... }
catch (Exception2 e) { .... }
catch (Exception3 e) { .... }
try{
return functionB(obj);
} catch (Exception1 e) { .... }
catch (Exception2 e) { .... }
catch (Exception3 e) { .... }
I have tried to create a function like below, but I am getting
Exception e1 is never thrown in try block
as expected.
public ResponseType callFunction(Function<ParamType, ResponseType> function, ParamType obj) {
try{
return function.apply(obj)
}catch (Exception1 e) { .... }
catch (Exception2 e) { .... }
catch (Exception3 e) { .... }
}
The issue is that Function.apply is not declared to throw any exceptions, so it is not generally possible to throw checked exceptions from an implementation, or to catch a checked exception from it at a call site. (Ignoring unusual workarounds as mentioned in the comments.)
However, Java does not restrict lambda expressions to only be used with standard functional interfaces, so the best approach when you need to handle specific exception types is to create your own.
#FunctionalInterface
interface MyFunction {
ResponseType apply(ParamType param) throws Exception1, Exception2, Exception3;
}
This can be used in a similar way to java.util.function.Function:
public ResponseType callFunction(MyFunction function, ParamType obj) {
try{
return function.apply(obj);
}
catch (Exception1 e) { throw new RuntimeException("Exception1"); }
catch (Exception2 e) { throw new RuntimeException("Exception2"); }
catch (Exception3 e) { throw new RuntimeException("Exception3"); }
}
(Modified to throw runtime exceptions in the catch blocks so that this will compile)
The calling code is identical to any standard functional interface:
callFunction(this::functionA, obj);
callFunction(this::functionB, obj);
or, equivalently:
callFunction(param -> functionA(param), obj);
callFunction(param -> functionB(param), obj);
I am contemplating throwing a RuntimeException inside the catch block to solve the missing return statement.
What would be way to handle this situation?
I think throwing an exception of some kind instead of return some meaningless value. .
private String tryObjMapper(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//missing return statement
}
It depends on what you want to be the fallback/default value or error handling
You have 2 main options (with 2 sub options):
1.A.Throw the exception:
private String tryObjMapper(Object obj) throws JsonProcessingException {
return objectMapper.writeValueAsString(obj);
}
1.B.Rethrow RuntimeException (or custom unchecked exception)
private String tryObjMapper(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException("Failed to map obj +" obj, e);
}
}
2.A.Define a default value on error
private String tryObjMapper(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;//or other default value
}
2.B.Define a default value with a single return statement:
private String tryObjMapper(Object obj) {
String retVal = null;//or other default value
try {
retVal = objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return retVal ;
}
Consider logging exception using logger and not using e.printStackTrace()
I think that the best way to handle it is to return null at both catch block ant the end of the function. You must check the returnee from the function whether null or not before usage.
Note: This solution is suitable if only you can't change the signature of the function to declare that it throws an exception. Otherwise, go with the signature update.
I have the following:
public void method(){
try {
methodThrowingIllegalArgumentException();
return;
} catch (IllegalArgumentException e) {
anotherMethodThrowingIllegalArgumentException();
return;
} catch (IllegalArgumentException eee){ //1
//do some
return;
} catch (SomeAnotherException ee) {
return;
}
}
Java does not allow us to catch the exception twice, so we got compile-rime error at //1. But I need to do exactly what I try to do:
try the methodThrowingIllegalArgumentException() method first and if it fails with IAE, try anotherMethodThrowingIllegalArgumentException();, if it fails with IAE too, do some and return. If it fails with SomeAnotherException just return.
How can I do that?
If the anotherMethodThrowingIllegalArgumentException() call inside the catch block may throw an exception it should be caught there, not as part of the "top level" try statement:
public void method(){
try{
methodThrowingIllegalArgumentException();
return;
catch (IllegalArgumentException e) {
try {
anotherMethodThrowingIllegalArgumentException();
return;
} catch(IllegalArgumentException eee){
//do some
return;
}
} catch (SomeAnotherException ee){
return;
}
}
This code below is the method header and body, but I get the following error: no exception of type object can be thrown an exception type must be a subclass of Throwable. I'm attempting to execute this block of code: catch(Object object).
public void method15665(Class435 class435, int i) {
do {
try {
try {
byte[] is
= new byte[(int) class435.method7563(1085678935)];
int i_3_;
for (int i_4_ = 0; i_4_ < is.length; i_4_ += i_3_) {
i_3_ = class435.method7564(is, i_4_, is.length - i_4_,
(byte) -10);
if (i_3_ == -1)
throw new EOFException();
}
Class224_Sub8 class224_sub8 = new Class224_Sub8(is);
if ((class224_sub8.aByteArray8535.length
- class224_sub8.anInt8536 * 475822179)
< 1) {
try {
class435.method7572(-1683167102);
} catch (Exception exception) {
/* empty */
}
break;
}
int i_5_ = class224_sub8.method13859((short) -7287);
if (i_5_ < 0 || i_5_ > 1) {
try {
class435.method7572(-1683167102);
} catch (Exception exception) {
/* empty */
}
break;
}
if ((class224_sub8.aByteArray8535.length
- class224_sub8.anInt8536 * 475822179)
< 2) {
try {
class435.method7572(-1683167102);
} catch (Exception exception) {
/* empty */
}
break;
}
int i_6_ = class224_sub8.method13737(2071056893);
if ((class224_sub8.aByteArray8535.length
- 475822179 * class224_sub8.anInt8536)
< 6 * i_6_) {
try {
class435.method7572(-1683167102);
} catch (Exception exception) {
/* empty */
}
break;
}
for (int i_7_ = 0; i_7_ < i_6_; i_7_++) {
Class323 class323
= Class399.aClass195_Sub2_Sub1_5932
.method14614(class224_sub8, -2141543778);
if ((Class255.aClass255_3016
== (((Class173_Sub1) this).aClass255Array9960
[class323.anInt5015 * 1568411443]))
&& (Class399.aClass195_Sub2_Sub1_5932.method14624
(class323.anInt5015 * 1568411443, 82620551)
.aClass350_2171.method6687
(-1035085164).aClass5162.isAssignableFrom
(class323.anObject5014.getClass())))
anInterface50_2149.method298((class323.anInt5015
* 1568411443),
class323.anObject5014,
-1250481088);
}
} catch (Exception exception) {
try {
class435.method7572(-1683167102);
} catch (Exception exception_8_) {
exception = exception_8_;
}
break;
}
try {
class435.method7572(-1683167102);
} catch (Exception exception) {
/* empty */
}
} catch (Object object) {
try {
class435.method7572(-1683167102);
} catch (Exception exception) {
/* empty */
}
throw object;
}
} while (false);
}
Does anyone know how fix this? It would be very much appreciated!
replace
} catch (Object object) {
with
} catch (Throwable object) {
actually you don't want to catch Throwable, but probably Exception, RuntimeException or an even more specific class.
You can only catch what can be thrown (IS-A Throwable). Hence, the compiler complains when you try to catch an Object (because it doesn't extend Throwable).
catch (Object o) // Error: Object IS-NOT Throwable
Throwable is inherited by all types of Errors and Exceptions. But, we usually don't catch Errors because a program almost always cannot recover from it for example, an OutOfMemoryError. So, a catch (Throwable t) is not recommended.
When using catch (Exception e) you basically have a catch-all for any exception (checked or un-checked) that might get thrown during the run. To use or not to use a generic catch usually depends on what you're try block is trying to do. For example, when reading a file you would like to handle and respond to a FileNotFoundException differently than say an EOFException.
All exceptions and errors extend Throwable, only those can be thrown and caught.
You can do
try{
throw new Exception();
}catch(Exception e){
// something here
}catch(Throwable t){
// something here
}
When you are writing multiple catch blocks, then keep following points in mind
You cannot write a subclass type AFTER a superclass type. i.e. If you write catch(RuntimeException rt){} AFTER catch(Exception e){} then you will get compiler error that it is already caught.
I'm working on some server-side code that wraps all exceptions before passing them to the client side, due to this all client facing methods have the following code
try{
DoSomething();
} catch (ExceptionA e) {
throw new CustomException(AType, e);
} catch (ExceptionB e) {
throw new CustomException(BType, e);
} catch (Exception e) {
throw new CustomException(Unexpected, e);
}
to have this repeated in every method seems to violate the DRY principle and I was wondering what the best way to refactor it would be. For instance I was thinking a wrapper method such as:
private void wrapException(Exception e) {
if (e instanceof ExceptionA) {
throw new CustomException(AType, e);
}
etc...
Take a look at AspectJ soften exception.
Also look at Guava's Throwables.
There is also Lamboks sneaky exception.
The other option is to use Anonymous object instances aka closures.
public abstract class Wrapper {
public void execute() {
try {
// do some boiler plate before
this.wrap();
// do some boiler plate after.
} catch (ExceptionA | ExceptionB ex) {
Type t = determineType(ex);
throw new CustomException(t, ex);
}
}
public void abstract wrap();
}
Now in your code you do something like:
new Wrapper() {
public void wrap() {
DoSomething();
}
}.execute()
This is possible in Java7 and up:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Copy-paste example from above doc:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
This is one way to go about it:
Exception caughtEx = null;
String extraInfo = null;
try{
DoSomething();
} catch (ExceptionA e) {
caughtEx = e;
extraInfo = AType;
} catch (ExceptionB e) {
caughtEx = e;
extraInfo = BType;
} catch (Exception e) { // catching Exception is usually a bad idea, just let it bubble up without catching...
caughtEx = e;
extraInfo = Unexpected;
}
if (caughtEx != null) throw new CustomException(extraInfo, caughtEx);