Kensuke Konishi
Kensuke Konishi

Reputation: 127

Is it faster to call a method as I initialise an object or hold it as a variable and call the method on that

Assuming that there is a class ClassA which gives a value that I need through non-static method.

In case when I just need a value from an instance of the ClassA, I guess there are two possible choices.

double value =0 ; // The value I actually need, the object is just transitory

1) ClassA a = new ClassA (hogehoge);
   value = a.getValue();

2) value = new ClassA(hogehoge).getValue();

I know there maybe an advantage or disadvantage for both. but generally speaking what is the difference between them?

in case 2), memory use is smaller than 1) or....

Upvotes: 9

Views: 470

Answers (7)

Rohit Jain
Rohit Jain

Reputation: 213261

The only difference is that in 2nd case, the object you created will be eligible for garbage collection immediately after that statement, as you don't have any reference to that object. You have an unnamed object there.

While in 1st case, since you have a reference to an object, you can access that object and its member later on also. So, it won't be eligible for garbage collection, [until it goes out of scope] (This statement, as discussed in the below comments, I'm still confused about. Will confirm this once I get the behind the scene concept), or there are no more reference created to that object, using reference assignment, or any other method.


BTW, in your 2nd case, you forgot a parenthesis there. It should be:

value = new ClassA(hogehoge).getValue();

Upvotes: 10

Matthias
Matthias

Reputation: 12259

Fun fact (a little bit OT): Under .NET, an object can actually be garbage collected before going out of scope - even while one of its methods is still executing (see sample code below or live demo at: http://rextester.com/WTKSYE61526 - prints out "False False" when ran under Release configuration and outside the debugger).

What does this tell us?
Well - a future version / different implementation of the JVM might implement a similar behavior (it's possible that there are even JVMs out there which already do).

Theoretically speaking (assuming a garbage collected environment), the two options can be considered equal. They might only be executed a little bit different during execution because of an implementation detail in the JVM (if they are not optimized as Andremoniy mentioned). And implementation details are subject to change.

So don't bother with the differences and go for the more readable one.

public class Program
{
    public static void Main(string[] args)
    {
        Program p = new Program();
        p.Foo();

        new Program().Foo();
    }

    public void Foo() 
    {
        WeakReference r = new WeakReference(this);

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        Console.WriteLine(r.IsAlive);
    }
}

Upvotes: 1

arshajii
arshajii

Reputation: 129507

You can view the bytecode for yourself:

double value = 0;
ClassA a = new ClassA();
value = a.getValue();
value = new ClassA().getValue();

becomes

   0: dconst_0      
   1: dstore_1                          // *double value = 0;*
   2: new           #2                  // class ClassA
   5: dup           
   6: invokespecial #3                  // Method ClassA."<init>":()V
   9: astore_3      
  10: aload_3       
  11: invokevirtual #4                  // Method ClassA.getValue:()D
  14: dstore_1      
  15: new           #2                  // class ClassA
  18: dup           
  19: invokespecial #3                  // Method ClassA."<init>":()V
  22: invokevirtual #4                  // Method ClassA.getValue:()D
  25: dstore_1      
  26: return  

Overall, there is no real difference between these two approaches in terms of speed, and you shouldn't worry about micro-optimizations like that.

Upvotes: 4

Bohemian
Bohemian

Reputation: 425043

Not much difference performance wise.

The main difference is that with the in-line version, the instance created is available for garbage collection as soon as the line finishes executing, and possibly before finishing, depending on the JVM.

Although creating an instance is fairly cheap, consider using a static method - so creating the instance and garbage collecting it can be avoided:

public static double getValue(HogeHoge hogehoge) {
    // some impl
}

Upvotes: 1

Andremoniy
Andremoniy

Reputation: 34900

Actually this two piece of code will have a small difference:

***** Class1.p
       8: invokespecial #4                  // Method ClassA."<init>":(Ljava/lang/String;)V
      11: astore_3
      12: aload_3
      13: invokevirtual #5                  // Method ClassA.getValue:()D
      16: dstore_1
      17: dload_1
      18: dreturn
}
***** CLASS2.P
       8: invokespecial #4                  // Method ClassA."<init>":(Ljava/lang/String;)V
      11: invokevirtual #5                  // Method ClassA.getValue:()D
      14: dstore_1
      15: dload_1
      16: dreturn
}
*****

I.e. we see here two additional instructions for variant #1:

      11: astore_3
      12: aload_3

But it seems, that after jvm warms-up these instructions will be optimized (eliminated) and it will be no difference at all.

Upvotes: 12

mariosangiorgio
mariosangiorgio

Reputation: 5543

My recommendation is to don't care about these micro optimizations and to focus more on readability of your source code.

I'd choose the solution that makes it easier to understand whats going on, even if it requires one more reference to be allocated.

In principle the version without the intermediate variable should, of course, save the memory required by the reference, which is negligible, and it should make available the object for garbage collector as soon as the operation is executed instead of when the reference goes out of the scope.

Also, note that that pieces of code may turn into the very same byte-code due to compiler optimization, which is another reason why you should not care about it.

Upvotes: 1

Tala
Tala

Reputation: 8928

Difference is negligible. The first case keeps reference a (4 bytes) to ClassA until it is garbage collected (for example when you return from your method).

Upvotes: 3

Related Questions