Reputation: 127
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
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
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
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
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
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
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
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