Sign up ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.
MyObj foo(){
    MyObj obj = null;
    try {
       //do something and init the obj.
    }
    catch (Exception e){
       Logger.log(e.getMessage());
    }
    return obj;
}

foo() can also return a null or an object. However, we can init obj in the first line by calling its default constructor.

MyObj obj = new MyObj();

Which way is bad and not recommended in Java? Is there coding standard on this?

share|improve this question

closed as off-topic by Jamal Feb 7 at 19:03

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

4  
By the way, you can return values from the try block. try { return new MyObj(); } catch (Exception e) { return null; } –  luiscubal Aug 26 '13 at 14:08
    
Why might the exception be thrown during foo()? If all you can do about it is log a message, it might make sense to have foo() throw an exception. This way the caller decides what to do and doesn't have to check for null. –  unholysampler Aug 26 '13 at 17:44

4 Answers 4

up vote 6 down vote accepted

This is a design consideration, not a standard. It all depends on what you want the client code to receive.

For example, in most cases if nothing is found or created, a method like this will return null rather than giving a placeholder object (which usually makes sense). However when dealing with a method which returns a list or set or objects, it's much more common to have the method return an empty list rather than null.

share|improve this answer

Returning null forces callers to check for the null. I try to remove all possibilities of getting null values back anywhere in the code base (because, as Bobby put it: it sucks). I would write the code as follows:

/**
 * Returns a MyObj instance that could be in an invalid state. Use the
 * <code>getReady()</code> method to determine whether the object
 * can be used.
 *
 * @return A valid MyObj instance, never null.
 * @see getReady()
 */
MyObj createSomethingObj() throws Exception {
  MyObj result = createObj();
  result.doSomething();

  return result;
}

/**
 * Allows subclasses to override. Subclasses must not
 * return null.
 *
 * @return A valid MyObj instance, never null.
 */
MyObj createObj() {
  return new MyObj();
}

Why return an invalid object reference at all? Using the code above subclasses can wrap their own instance of MyObj():

MyObj createObj() {
  return new MyObjSubclass();
}

Or even:

MyObj createObj() {
  return new MyObjSubclass( super.createObj() );
}

Also consider that "logging" is a cross-cutting concern. Read about Aspect Oriented Programming (AOP) to see an alternative to littering the code with debugging.

If you absolutely must return null, comment the reason why using JavaDocs so that clients to the class can use an assertion to validate the object.

share|improve this answer
    
I disagree with this. If I was using code that was using placeholder objects like this, I would just have to do an even more convoluted check to figure out if the createSomethingObj() method actually returned something meaningful, probably something which is based on the semantics of the program (such as if(obj.getControlNumber() < 1). if(obj == null) is a quick and easy way to do it. Plus a good coder in a production environment would do the null checking anyway, so we would just have if(obj != null && obj.getControlNumber() < 1), making the code even more convoluted. –  asteri Aug 27 '13 at 15:09
    
@JeffGohlke: Accessor methods can be avoided most of the time. Methods simply should not return null objects (see also: Hoare's billion dollar mistake): they should return usable objects. Bobby showed how to avoid the convoluted mechanisms you describe: if( obj.isReady() ). For what it is worth, a "good coder" would document the @return value of the method to indicate whether or not a null object could be returned. –  Dave Jarvis Aug 27 '13 at 16:05
    
Consider a practical example. readFromDatabase(int id), which returns a DatabaseObject. If the passed-in ID doesn't exist in the database, null is a much more sensible response than a DatabaseObject with a bunch of default, meaningless values. Having a "usable object" in this case is detrimental, and null is more meaningful to the caller. –  asteri Aug 27 '13 at 16:21
    
@JeffGohlke: Without getting into too much further discussion, using a database requires a persistence layer from which business objects are created. If your business objects are reading integer values directly from a database, the infrastructure is wrong. –  Dave Jarvis Aug 27 '13 at 16:25

Both methods are fine, the important part is that in the end it does not matter as long as the behavior is documented.

I would also clean your code up a little:

/**
 * Creates a new MyObject, returns null on failure and logs the exception.
 * @return A new MyObject or null on failure.
 */
public MyObject foo() {
    try {
        MyObject myObject = new MyObject();
        myObject.manipualteData();
        myObject.reticulateSplines();
        return myObject;
    } catch (DontCatchGenericExceptions ex) {
        LOGGER.log(Level.SEVER, "Creation of MyObject failed!", ex);
    }

    return null;
}

If you don't want to return null (because, let's face it, sometimes it sucks) you can also throw the exception and let it be handled above you:

/**
 * Creates a new MyObject.
 * @return A new MyObject.
 * @throws YourCustomException If the creation of MyObject failed.
 */
public MyObject foo() throws YourCustomException {
    MyObject myObject = new MyObject();
    myObject.manipualteData();
    myObject.reticulateSplines();
    return myObject;
}

If you want to return an Object and handle the exception yourself, I'd suggest to expand the Object by a field which does allow the user to check for readiness of the returned Object:

public class MyObject {
    private boolean ready = false;

    public boolean isReady() {
        return ready;
    }

    public void finishInitialization() {
        if(ready) {
            // It was called a second time,
            // maybe you want to throw an exception?
        }

        ready = true;
    }
}

/**
 * Creates a new MyObject.
 * @return A new MyObject.
 */
public MyObject foo() {
    MyObject myObject = new MyObject();
    try {
        myObject.manipualteData();
        myObject.reticulateSplines();
        myObject.finishInitialization();
        return myObject;
    } catch (DontCatchGenericExceptions ex) {
        LOGGER.log(Level.SEVER, "Creation of MyObject failed!", ex);
    }

    return myObject;
}

This way the user of your function/object can easily check if the returned Object was actually usable:

MyObject myObject = foo();
if(myObject.isReady()) {
    // Do something here with myObject
} else {
    // This sucks! The object-creation failed.
}

Though, this only avoids the null-check, but it's basically the same code as if you'd return null directly.

Also be aware that my little documentation here is not the best example on how to do JavaDoc documentation. It needs to be better worded and extended.

share|improve this answer
1  
I recommend against returning objects in an unready state. Either a) throw/propagate an exception, b) return null, c) return a "placeholder" or "proxy" object to essentially defer initialization (lazy loading). The possibility of objects in a bad state makes them harder to use correctly. –  200_success Aug 27 '13 at 17:28
    
@200_success: I agree. –  Bobby Aug 27 '13 at 18:11

Good practice in such cases is to return Optional introduced in Java 8 (or use Optional from Guava library if Java 8 is not an option).

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.