tags:

views:

183

answers:

8

Hi...

maybe it's dumb but is there a difference between

new Something().method();

and

Something tmpSomething = new Something();
tmpSomething.method();

as I was calling only one method on this particular object, I chose the first solution but I'm not sure that this is exactly the same behavior...

I just want to mention the constructor initializes a Writer and method writes in this file...

+2  A: 

They are the same. Although constructing an object and only calling a single method on it may indicate poor design. Why not allow Something.method(); without needing to expose a constructor?

Tom Hawtin - tackline
+1  A: 

Well, in the second case you've got the object tmpSomething so you can use it throughout in the code but in the first example you don't. So you can't.

I imagine the first method is probably a touch more efficient but probably not the best practice for Java conventions.

Andrew Weir
I would consider any convention that would force you to pollute your scope with unnecessary variables a "worst practice"
Michael Borgwardt
Ah, good point sir. I shall leave my answer up with no edits so others may learn too!
Andrew Weir
+3  A: 

There is no difference whatsoever except that in the second case you have an unnecessary variable lying around that makes the code harder to maintain.

Also, objects that get created only to be discarded after calling a single method constitute a code smell.

Michael Borgwardt
I didn't know this term... :-) ... I think there are some exceptions though...
LB
I don't agree, see Joshua Bloch, Builder Pattern new Object.Builder(required_param1, required_param2, ...).build()
adrian.tarau
Yes, there are exceptions. A code smell doesn't *always* mean something is wrong. As for the Builder pattern: its point is to have optional other methods that get usually called before build()
Michael Borgwardt
Yes, if the normal usage pattern of this code is to discard the object after calling a single method, then the method should almost certainly be static.
Ian McLaird
+1  A: 

If you can get some value from the first call maybe you might want to define your method static:

public static ____ method() {
}
victor hugo
A: 

Firstly I'll agree with everyone else and say they are the same in terms of function.

However, I'm of the opposite opinion on what most are saying in this post, which is that I think the first example is the way to go.

And with the first example, I'd extend it even further with some form of dependency injection. This will get you in the habit of giving you the ability to test things if you need to inject a mock/test version of that 'Something' class.

Also by not train wrecking (doing more than one operation on the one line which is a code smell, e.g. new dog().getEyes().getColour();), in my opinion improves readability as well as optimises your ability to refactor later on. Just because at the moment you only call that one method on that object doesn't mean you won't need that object to do something else on it later meaning you will have to extract a variable for that 'Something' object anyway.

digiarnie
+1  A: 

There is a subtle difference between the two snippets, but only when viewed within their scope. Consider them within methods:

  public void doSomething1() {
    new Something().method();
    doSomeLongRunningSomething();   
  }

  public void doSomething2() {
    Something tmpSomething = new Something();
    tmpSomething.method();
    doSomeLongRunningSomething();   
  }

In the first method, the 'something' is immediately available for garbage collection while in the second method, tmpSomething stays within scope during the run of doSomeLongRunningSomething. If you are doing anything interesting during the finalize (e.g. closing the file), this could introduce some quirks.

That said, my preference is for the second example and naming the new instance as it assists the debugging processing. While stepping through code you have a named instance that is easier to watch. That doesn't apply when you're getting pre-existing instances in which case I find chaining methods more readable, e.g. myDog.getEyes().getLeftEye().getColorAsRgb().getRed().

Adrian
I guess everyone has their own preference in regards to chaining.I find no-chaining more helpful when you do a lot of refactoring to keep your code tidy and avoid duplication.If you you had a class that had two lines:myDog.getEyes().getLeftEye();myDog.getEyes().getLefteye().getColorAsRgb().getRed();Then a tool such as simian would not pick up duplication whereas I would want to be told that I would actually want to extract a method like this:private Eye getLeftEye(Dog dog) { Eyes eyes = dog.getEyes(); return eyes.getLeftEye();}Of course this is a trivial example. Dupe = bad.
digiarnie
Assuming the compiler performs liveness analysis, the two methods should compile to exactly the same bytecodes. Anyone care to check?
Andrew Duffy
I've followed up on this comment in response to Andrew's more elaborate post...
Adrian
+3  A: 

I did a quick test. This is the extremely trivial test code:

public class TestLiveness
{
    public static void test1()
    {
        System.out.println(new Square(4).square());
        count();
    }

    public static void test2()
    {
        Square t = new Square(4);
        System.out.println(t.square());
        count();
    }

    private static void count()
    {
        for(int i=0; i<1000000; i++)
            System.out.println(i);
    }

    static class Square
    {
        private int val;

        Square(int val)
        {
            this.val = val;
        }

        int square()
        {
            return val * val;
        }
    }
}

Javap shows that the two methods are compiled differently; chaining doesn't touch the local variable table whereas the temporary variable does indeed stick around until the method returns. However, the VM/JIT compiler may still perform liveness analysis and allow the instance to be garbage collected before the method returns.

public static void test1();
  Code:
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   new     #3; //class TestLiveness$Square
   6:   dup
   7:   iconst_4
   8:   invokespecial   #4; //Method TestLiveness$Square."<init>":(I)V
   11:  invokevirtual   #5; //Method TestLiveness$Square.square:()I
   14:  invokevirtual   #6; //Method java/io/PrintStream.println:(I)V
   17:  invokestatic    #7; //Method count:()V
   20:  return

public static void test2();
  Code:
   0:   new     #3; //class TestLiveness$Square
   3:   dup
   4:   iconst_4
   5:   invokespecial   #4; //Method TestLiveness$Square."<init>":(I)V
   8:   astore_0
   9:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   12:  aload_0
   13:  invokevirtual   #5; //Method TestLiveness$Square.square:()I
   16:  invokevirtual   #6; //Method java/io/PrintStream.println:(I)V
   19:  invokestatic    #7; //Method count:()V
   22:  return
Andrew Duffy
+1 for going through the effort to give an authoritative response!Following on from your comment, I recall that the JVM specification requires garbage collection exists but goes out of its way to not specify *how* it is implemented. So, a JVM could choose to implement as you suggest or not. I'm betting that in practice it is not a huge speed-up so is generally ignored.
Adrian
and also, the scope of a variable should be as narrow as possible - and having a temp variable that is only used once remain in scope could potentially cause maintenance problems later on.
Chii
I don't have the reflex of using javap... i should...my problem is still not solved but i'm making progress..
LB
A: 

Nothing wrong with that, even when you call only one function.

Have a look at Fluent Interfaces on Wikipedia or Fluent Interfaces by Martin Fowler

adrian.tarau