See the two examples below. Assume both classes contains public methods belonging to a widely used API library.
AClass.java is easier to write (maybe easier to read due to less noise), but when error is detected, the first method in stack trace is an internal method (nullCheck(...)) and the exception message is not referring to that method. Could this cause unnecessary confusion to the user? I mean in the sense of the user thinking: "it's an internal method which has thrown an exception, must be a bug in the library, not a fault in my program. What a ** useless library..."
BClass.java is more tiresome to write (with all its if statements), but when error is detected the first line of the stack trace pinpoints the API method (called by user) where error was first detected. Would this more likely make user think: "I'm calling that method from my code, must be something wrong with the parameter I'm passing in".
Which would be the preferred way of throwing exception when checking parameters for validity in a public API? Or are the two examples considered equal?
public class AClass {
public void publicApiMethod1(String a){
nullCheck(a, "a");
// do something...
}
public void publicApiMethod2(String a, String b, String c){
nullCheck(a, "a");
nullCheck(b, "b");
nullCheck(c, "c");
// do something...
}
private void nullCheck(Object a, String argName) {
if(a == null){
throw new NullPointerException("Null argument: " + argName);
}
}
}
public class BClass {
public void publicApiMethod1(String a){
if(a == null){
throw new NullPointerException("Null argument: 'a'");
}
// do something...
}
public void publicApiMethod2(String a, String b, String c){
if(a == null){
throw new NullPointerException("Null argument: 'a'");
}
if(b == null){
throw new NullPointerException("Null argument: 'b'");
}
if(c == null){
throw new NullPointerException("Null argument: 'c'");
}
// do something...
}
}
If your error message is descriptive (and it is), no one will bother to look at the stack trace. Thus the first form is better because it encapsulates the validation logic.
Note that there are plenty of assertion methods in various libraries ready to use, see: Objects.requireNonNull and Validate.notNull).
I would do it that way, basically based on your AClass:
public void publicApiMethod2(String a, String b, String c){
try {
nullCheck(a, "a");
nullCheck(b, "b");
nullCheck(c, "c");
}
// catch the NullPointerException,
// and any other Exception explicitly thrown by your validation methods
catch (NullPointerException e) {
throw new IllegalArgumentException(e.getMessage());
}
// do something...
}
That way, the user gets an explicit message and a stacktrace that points to the public method.
in your b class why dont you use
if( (c == null)|| (b == null)|| (a == null) ){
//thrown my red ball
}
less tiresome, more readable
I would think that Class A is fine, as long as you clearly document it with a #throws. I have seen plenty of libraries that will throw deeper in the stack. The important thing is for the user to understand WHY an error was thrown and what they can do to avoid it.
Related
I have a method using throws, inside is two if/else statements, the if statement tests a condition and then throws an exception if it fails, the problem is of course is that if the first if/else block fails my second never gets executed, is there an alternative way to approach this problem?
EDIT (Further Information)
My code is checking whether a person object has the correct first name Test 1, or the correct surname Test 2, if not throw exception A or B, code further on then adds the person into a group if they pass both conditions
Method throws Exception A, Exception B
{
//Test First name
if(Test1)
{
If persons firstname is correct, Test1 is true
}
else
{
throw new Exception A
}
//Test Surname
if(Test2)
{
If persons surname is correct, Test2 is true
}
else
{
throw new Exception B
}
//If everything is fine, add the person to a list.
if (Test1 & Test2)
{
Add Person to a list
}
}
Based upon your description, I am thinking that you could change to
if(Test1)
{
if(!Test2)
{
throw new Exception B
}
// Do some work here
}
else
{
throw new Exception A
}
Another way to consider is by creating methods
bool test1 = correctFirstName (fname);
bool test2 = correctLastName (lname);
if (test1 && test2)
{
// do some stuff
}
else {
if (!test1) // throw ExceptionA
else // throw ExceptionB
}
Something like this should work. I would of course recommend not using generic Exception, but I would also not use two different types of exceptions as your original code implied.
Method throws Exception A, Exception B
{
String errMsg = "";
//Test First name
if(Test1)
{
If persons firstname is correct, Test1 is true
}
else
{
errMsg = "Invalid first name";
}
//Test Surname
if(Test2)
{
If persons surname is correct, Test2 is true
}
else
{
errMsg = "Invalid surname";
}
//If everything is fine, add the person to a list.
if (errMsg.equals(""));
{
Add Person to a list
}
else
{
throw new Exception(errMsg);
}
}
It appears the task is not possible, the instructions given to me did not state that in order to trigger one Exception or the other I had to comment out code.
I am trying to implement a search function. The function returns an object of type Prestamo if it finds a matching element. The function shouldn't return anything if nothing is found, but I get (of course) an error complaining about a missing return statement. How is this kind of problem solved? I guess Try-catch could be my friend for this, but I am struggling to understand that syntax.
This is my code:
public Prestamo buscarPrestamoPorUUID(UUID idPrestamo, ArrayList<Prestamo> listaBuscar) {
Iterator<Prestamo> it = listaBuscar.iterator();
Prestamo esteElemento;
while (it.hasNext()) {
esteElemento = it.next();
if (esteElemento.getActivo() && esteElemento.getIdPrestamo().equals(idPrestamo)) {
return esteElemento;
}
}
}
In Java, the control over a method must end in one of two ways:
A return statement, which returns an object of the type declared in the method signature OR null
A thrown exception (if the Exception does not extend RuntimeException, it must be declared in the method signature).
To resolve your compilation error, you need to do one of the two. If you want to do the former, it'd probably look something like this:
public Prestamo buscarPrestamoPorUUID(UUID idPrestamo, ArrayList<Prestamo> listaBuscar) {
Iterator<Prestamo> it = listaBuscar.iterator();
Prestamo esteElemento;
while (it.hasNext()) {
esteElemento = it.next();
if (esteElemento.getActivo() && esteElemento.getIdPrestamo().equals(idPrestamo)) {
return esteElemento;
}
}
return null;
}
Just be sure that the logic that invokes this method is prepared to handle null.
If you want to do the second, you'd do something like this:
public Prestamo buscarPrestamoPorUUID(UUID idPrestamo, ArrayList<Prestamo> listaBuscar) {
Iterator<Prestamo> it = listaBuscar.iterator();
Prestamo esteElemento;
while (it.hasNext()) {
esteElemento = it.next();
if (esteElemento.getActivo() && esteElemento.getIdPrestamo().equals(idPrestamo)) {
return esteElemento;
}
}
throw new RuntimeException("Didn't find an entity with the provided UUID!");
}
I personally prefer the former to the latter. It's a perfectly-valid use of null, and it makes the method easier to use than having to worry about uncaught exceptions. Regardless, note how that either implementation reaches a return or throw statement eventually. That's what your compiler checks for.
(P.S.: You can replace your while-loop with a for-each loop for code clarity.)
You could have it return null when no match is found. This would require the caller of the buscarPrestamoPorUUID() method to do a test for null and handle appropriately using a try/catch or some other way to handle it. ie:
Prestamo test = buscarPrestamoPorUUID(someID, someList);
if(test == null)
{ /* handle no match found */ }
else
{ /* handle result found */ }
Often in java I have to get a value of a property of an object which is deep in this object. For example, if I'm sure that all my sub-objects are not null, I can do that :
public function getDeepValue(A a) {
String value = a.getB().getC().getListeD().get(0).getE().getValue();
return value;
}
But in case of sub objects of the parent can be null, I have to test every object.
To do that, I see 2/3 solutions :
First, step by step :
public function getDeepValue(A a) {
if(a == null){
return null;
}
B b = a.getB();
if(b == null) {
return null;
}
C c = b.getC();
if(c == null){
return null;
}
List<D> ds = c.getListeD();
if(ds == null || ds.size() == 0){
return null;
}
D d = ds.get(0);
if(d == null) {
return null;
}
E e = d.getE()
if(e == null){
return null;
}
return e.getValue();
}
Second, test all in one if block, soooo dirty :
public function getDeepValue(A a) {
if(a != null && a.getB() != null && a.getB().getC() != null && a.getB().getC().getListeD() != null && a.getB().getC().getListeD().size() > 0 && a.getB().getC().getListeD().get(0) != null && a.getB().getC().getListeD().get(0).getE() != null){
return a.getB().getC().getListeD().get(0).getE().getValue();
}
return null;
}
Third solution, using a try catch block :
public function getDeepValue(A a) {
try {
return a.getB().getC().getListeD().get(0).getE().getValue();
} catch(NullPointerException e) {
return null;
} catch(IndexOutOfBoundsException e) {
return null;
}
}
Solution 1 seems not too bad but needs a lot of code. It is generally the solution I use.
Solution 2 is for me really dirty...
In paper, I realy like solution 3, but is it a good solution in term of performances ?
Is there any others acceptables solutions ?
Thanks for help, I hope my english is not too bad..
Regards
Solution #3 looks simple, but it can potentially hide a whole host of problems. It might be an adequate solution if you have full access to all of the classes in the chain and you know what's going on in each method and you can guarantee those methods won't cause problems with your try/catch and you're never going to change them... that's a lot of conditions to make it a worthwhile solution, but I can conceive that it's possibly a useful sufficient one.
Solution #2 looks horrid to me, especially if one or more of the get methods is a bottleneck (such as a slow database query or using a blocking network connection). The earlier in the chain such a potential bottleneck, the worse it would potentially be, as you're calling it over and over again. This of course depends on the implementation of the methods in question (even if one of them is slow, the result could be cached, for example), but you shouldn't need to know that in your client code. Even with efficient or trivial implementations, you've still got the overhead of repeated method calls you oughtn't need.
Solution #1 is the best of the three, but it's likely not the best possible. This solution takes more lines of code than the other two, but it doesn't repeat itself and it isn't going to be tripped up by the implementations of the other methods. (Note: If you do not have access to the classes in the chain for refactoring, I would use this solution.)
A better solution than #1 would be to refactor the classes so that the client code doesn't need to know about this chain at all. Something along these lines:
class Client {
public Mumble getDeepValue(A a) { return a == null ? null : a.getDeepValue(); }
}
class A {
private B b;
public Mumble getDeepValue() { return b == null ? null : b.getDeepValue(); }
}
class B {
private C c;
public Mumble getDeepValue() { return c == null ? null : c.getDeepValue(); }
}
class C {
private List<D> ds;
public Mumble getDeepValue() {
D d = ds == null || ds.size() == 0 ? null : ds.get(0);
return d == null ? null : d.getDeepValue();
}
}
class D {
private E e;
public Mumble getDeepValue() { return e == null ? null : e.getMumble(); }
}
class E {
private Mumble m;
public Mumble getMumble() { return m; }
}
As you can see, the longest chain any of these classes has is to access the public members of an element of a collection that is a private member of the class. (Essentially ds.get(0).getDeepValue()) The client code doesn't know how deep the rabbit hole goes, only that A exposes a method which returns a Mumble. Client doesn't even need to know that the classes B, C, D, E, or List exist anywhere!
Additionally, if I were designing this system from the ground up, I would take a good long look at whether it could be restructured such that the actual Mumble object wasn't so deep. If I could reasonably get away with storing the Mumble within A or B, I'd recommend doing it. Depending on the application, that may not be possible however.
in terms of performance solution 3 is the best one. In addition It is neat and easy to understand , For example looking at a loop example:
int[] b = somevalue;
for(int i=0;i<b.length;i++){
//do something
}
in this case for every iteration we execute the condition. However, there is another approach for it which uses try and catch
int[] b = somevalue;
try{
for(int i=0;;i++){
//do something
}
}catch(IndexOutOfBoundException e){
// do something
}
on the second solution,the loop keeps going until we reach the end of the loop which then it throws IndexOutOfBoundException as soon as we reach the end of the array. meaning we don't check for the condition no more. thus faster.
What's in java the correct method to handle method params/inner errors?
All the three methods do the same thing, with a little difference in the second one where exception also have a "caused by" section.
Please not that in the third method, the return must be repeated every time i want to exit from it.
Consider also that exception handling is quite expensive in java (i've read this somewhere).
Thanks!!
public static String method(String arg) {
block: {
if (arg == null) {
logger.error("arg is null");
break block;
}
try {
...
return "ok";
} catch (Exception e)
logger.error("help!", e);
}
}
return "ko";
}
public static String method(String arg) {
try {
if (arg == null) {
throw new Exception("arg is null");
}
...
return "ok";
} catch (Exception e) {
logger.error("help!", e);
return "ko";
}
}
public static String method(String arg) {
String result = "ko";
if (arg == null) {
logger.error("arg is null");
return result;
}
try {
..
result = "ok";
} catch(Exception e) {
logger.error("help!", e);
}
return result;
}
EDIT:
Also, in the second method, you can differentiate inner method errors by using RuntimeException (or a custom one), bad idea?
I don't think the "right" way is any of these 3.
Java has an exception just for invalid parameters, called IllegalArgumentException, which is actually a RuntimeException, so you don't declare it. The idea is that if you provide an illegal argument, this is a bug in the caller side, so the caller must catch and deal with the exception.
When your method returns a valid result for an "illegal" argument, IMO, your argument is not really illegal, so there shouldn't be an exception and then there's nothing to recover from. And so, your code should look like
public static String method(String arg) {
return arg==null?"ko":"ok";
}
No exceptions here.
Now, if a null argument is something exceptional that you have to deal with, I think the right approach is to treat it in the caller side. In the JDK, you'll find examples of both explicit and implicit invalid argument exceptions, for example:
Explicit
* #param s the string to be parsed.
* #return a {#code Double} object holding the value
* represented by the {#code String} argument.
* #throws NumberFormatException if the string does not contain a
* parsable number.
*/
public static Double valueOf(String s) throws NumberFormatException {
return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
}
Implicit
* #param uri
* the URI to convert
*
* #return the resulting {#code Path}
*
* #throws IllegalArgumentException
* if preconditions on the {#code uri} parameter do not hold. The
* format of the URI is provider specific.
(...)
*/
public static Path get(URI uri) {
String scheme = uri.getScheme();
if (scheme == null)
throw new IllegalArgumentException("Missing scheme");
(...)
I think the whole idea here is
if a null arg is an exceptional situation, not expected by your method, then it's a bug and you must recover from it outside the called method. If the called method can deal with the null arg (returning for example some valid value such as "ko") then it's not an exceptional situation, but just a valid argument for which there's a valid result, so no exceptions are needed here.
otherwise, you must throw an exception (explicit or not) and let the caller deal with it
That's what I think.
Up for the first one, cause it's more elegant, but third one is more clear to read and less error prone imho.
You should use the one that is easiest to read. Remember that code is written once and read many times.
The third one is the most easiest to read.
Another rule which is pretty good. One entry one exist for every method.
It is preferable to only use one return statement.
The reason is that it is easier for the next reader to understand what the thought is with the code.
More about this kinds of issue, you can read about in Clean Code http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
Suggestion for one entry-exist solution:
public static String method(String arg) {
String outString = "ko";
try {
if (arg != null) {
outString = "ok";
} else {
logger.debug("arg is null");
}
} catch (Exception e) {
logger.error("Help!", e);
}
return outString;
}
Is it possible to wrap following code in a reusable function?
EDIT: this is just an example, I want a working solution for ALL recursion depths
what I want is that following code is generated:
if (MyObject o == null ||
o.getSubObject() == null ||
o..getSubObject().getSubSubObject() == null /*||
... */)
return defaultValue;
return o.getSubObject().getSubObject()/*...*/.getDesiredValue();
by calling something like
Object defaultValue = null;
Object result = NullSafeCall(o.getSubObject().getSubObject()/*...*/.getDesiredValue(), defaultValue);
The seond code block is just an idea, I don't care how it looks like, all I want is that I, if desired, can avoid all the null checks before calling a deeper function...
Injection could do this propably, but is there no other/easier solution? Never looked at injection before yet...
EDIT2: example in another language: http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator
Not really, any code you would write this way would look horrible and/or use very slow reflection. Unless you use an actual Java preprocessor that can understand and change the code you've written.
A better (but associated with quite a bit of refactoring) approach would be to make sure that the values in question cannot possibly be null. For example, you could modify the individual accessors (getSubObject(), getDesiredValue()) to never return null in the first place: make them return default values. The accessors on the default values return default values in turn.
Java8 helps to get the closest you'll get to your syntax with decent performance I suspect;
// Evaluate with default 5 if anything returns null.
int result = Optional.eval(5, o, x->x.getSubObject(), x->x.getDesiredValue());
This can be done with this utility class;
class Optional {
public static <T, Tdef, T1> Tdef eval(Tdef def, T input, Function<T,T1> fn1,
Function<T1, Tdef> fn2)
{
if(input == null) return def;
T1 res1 = fn1.apply(input);
if(res1 == null) return def;
return fn2.apply(res1);
}
}
Sadly, you'll need a separate eval() defined per number of method calls in the chain, so you may want to define a few, but compile time type safe and reusable with just about any calls/types.
You can do something like this
public static Object NullSafeCall(MyObject o,Object defaultValue){
if ( o == null || o.getSubObject() == null)
{
return defaultValue;
}
else
{
return o.getSubObject().getDesiredValue();
}
}
Now you can call this method as follows
Object result = NullSafeCall(o, defaultValue);
i would suggest just replace
Object result = NullSafeCall(o.getSubObject().getDesiredValue(), defaultValue);
by the
Object result = (o == null || o.subObject == null) ? defaultVlue : o.getSubObject().getDesiredValue();
Create method only if you can reuse it......
What you want is not possible. It is essential to understand that using this syntax: Object result = NullSafeCall(o.getSubObject().getSubObject() ...); the part of o.getSubObject().getSubObject() will be evaluated before any control passes to the function/method thus throwing the exception.
It is required to have some type of context before executing such code. The closest to this I could think of, can be done using anonymous inner classes like the example below:
// intended to be implemented by an anonymous inner class
interface NullSafeOperation<T> {
public T executeSafely();
};
// our executor that executes operations safely
public static class NullSafeExecutor<T> {
public NullSafeExecutor() {}
public T execute(T defaultValue, NullSafeOperation<T> nso) {
T result = defaultValue;
try {
result = nso.executeSafely();
} catch(NullPointerException e) {
// ignore
}
return result;
}
// utility method to create a new instance and execute in one step
public static <T> T executeOperation(T defaultValue, NullSafeOperation<T> nso) {
NullSafeExecutor<T> e = new NullSafeExecutor<T>();
T result = e.execute(defaultValue, nso);
return result;
}
}
public static void main(String[] args) {
final String aNullString = null;
String result = NullSafeExecutor.executeOperation("MyDefault", new NullSafeOperation<String>() {
#Override
public String executeSafely() {
// trying to call a method on a null string
// it will throw NullPointerException but it will be catched by the executor
return aNullString.trim();
}
});
System.out.println("Output = " + result); // prints: Output = MyDefault
}