I have this two codes:
A a = new A();
B b = a.getB();
B b = new A().getB();
In the first code I created two objects and saved them so the program need memory for two objects
but in the second code I created object from A and I didn't saved it in any variable so my question is :
what is the different between this two codes? is it just a syntax or there is an effect on memory?
Reference/Pointer versus Object
Your term "saved" has no technical meaning, and may be confusing you.
Let’s get more concrete. Replace A
class with Cat
class. Replace B
class with Breed
class.
Let's assume that when instantiating a Cat
we also instantiate a Breed
object held within that Cat
object. In other words, we are not doing lazy-loading in this example. So when instantiating a Cat
, we pass along an instance of Breed
to the constructor.
Two lines
The Cat a
variable does not hold a Cat
object, it holds a reference (a pointer) to the Cat
object that was constructed elsewhere in memory. That location of the Cat
object in memory, basically a number, is what is held by the Cat a
.
Cat a = new Cat( "Fluffy" , new Breed( "Tabby" ) ) ; Passing new instance of `Breed` to constructor of `Cat`, with resulting `Cat` object’s location in memory being returned to the `a` reference/pointer variable.
You can think of that line of code as this:
Pointer-holding-memory-location-of-object-of-class-Cat a = Instantiate-a-new-Cat-object-somewhere-in-memory-and-return-its-memory-location( … ) ;
Conceptual diagram:
Notice that the only way to access the Breed
object is to go through the Cat
object Fluffy
. The only way our code can get to that Cat
object is through the reference/pointer variable named a
.
Breed b = a.getBreed() ; // Accessing the `Cat` instance, then traversing to the `Breed` object.
After that code we have wee bit of memory now allocated to holding another pointer/reference, the variable named b
. The b
variable is not Cat
nor a Breed
, it is the memory location of where to find the Breed
object elsewhere in memory. We can now directly access the Breed
object, without going through the Cat
instance.
Conceptual diagram:
One line
Your other code:
B b = new A().getB() ;
…converted to our example:
Breed b = new Cat( "Fluffy" , new Breed( "Tabby" ) ).getBreed() ;
…is quite similar, but never establishes the reference a
as a named variable. The reference is generated, at least conceptually (in actuality a JVM may have optimizations). The brief ephemeral reference is used to immediately call the getBreed
method.
After obtaining a memory-location of the Breed
object, the ephemeral reference to the new Cat
object is released, and the new Cat
object falls out of scope. The new Cat
object technically is likely still floating in memory for a moment, becoming a candidate for garbage-collection, due to be purged from memory.
Of course the new one-liner seen above using Cat
and Breed
becomes silly: We instantiate a new Breed
, pass it to the constructor of Cat
, and then immediately ask to get it back. Let’s ignore the awkward silliness for the sake of this memory-management discussion.
Conceptual diagram:
As for memory management, the same amount of memory is likely taken in both your scenarios (depending on your JVM implementation). Both scenarios are establishing a pair of objects and a pair of references. The one slight difference is that in your second scenario the Cat
object and its ephemeral pointer go out of scope immediately, and become candidates for garbage-collection. So memory might be reclaimed sooner than in your first scenario. In practice, the difference would likely be insignificant.
Do not micro-optimize
As others commented, all this is merely academic. You generally should not worry about such micro-optimizations.
The modern compilers and JVMs are extremely well-optimized, some of the most well-optimized and well-tested large software projects ever. So the best way to write Java code is simply. Write simple easy-to-read and easy-to-understand code for humans, and you will also be writing code that is most likely to be well-optimized by the compiler and JVM. Trying to be clever by out-thinking the compiler & JVM is ironically liable to be counter-productive, resulting is less-optimized code.
For light objects, very few differences.
In the first code the A object is assigned to a variable. So it is eligible to be garbage collected only as the variable is out of the scope.
In the second code the A object is not assigned to a variable. So it is right now eligible to be garbage collected.
In a general way you should not worry about this kind of things and using a variable or not using it only if it makes sense.
You kinda answered your own question. In the first example, you created two variables 'A' and 'B' so more memory is used. In the second example, you only created on variable B, so less memory is used. In the second example, a new 'A' is created then the newly object calls the method getB() and the result is stored in the variable 'B'. In this situation the memory difference is very minimal, but if this was repeated multiple times over the course of a program then the memory usage could stack up.
Also, Java has its own garbage collector and when it runs it collects/deleted the memory of the objects that are no longer accessible. Once a variable goes out of scope, then the garbage collection can run and clean up that unused memory.
With the garage collector in place, the memory difference in the two statements almost does not matter.