This question already has answers here:
Should I instantiate instance variables on declaration or in the constructor?
(15 answers)
Closed 9 years ago.
We can do :
class A {
// some code
}
class B {
A obj = new A(); // ???
}
Query :
My understanding is that the instance obj (of class A) is not static therefore not available in Class memory of B
In that case, will it be initialized for every instance of B?
In the case that obj actually stays in Class memory of B (i.e., static), then when will the initialization of instance obj happen?
Either way, is this a good practice ?
Then why do we have constructors if we can do this?
Feel free to correct me.
Fields initialized like this are common practice.
You can think of them as being part of the constructor, similar to instance initializer blocks.
We still have constructors, because you want to take parameters and have complex logic sometimes.
The pattern is especially convenient if you have more than one constructor (the fields will be initialized for every code path).
A is not static therefore not available in Class memory.
Correct. You have to have an instance of B to get at the field A obj.
will it be preinitialized for every object of B ?
Yes. A separate new A will be created for every B created.
If this has to stay in obj memory then when will this initialization happen ?
N/A
Either way is it a good practice ?
Yes. It's called object composition and composing objects from other objects is one of the two main means of decomposing a problem using Object-Oriented design. The other one is inheritance.
Then why do we have constructors if we can do this ?
This is just syntactic sugar. All the below are equivalent.
class B {
A obj = new A(); // field initializer
}
class B {
A obj;
B() {
A = new A(); // initialized in constructor
}
}
class B {
A obj;
{ obj = new A(); } // instance initializer
}
As long as nothing reads obj during initialization, there's no observable difference between doing initialization in a field, constructor, or explicit initializer.
Sometimes it's just more convenient to assign a value where the field is declared.
A is not static therefore not available in Class memory.
Right.class A will be instantiated whenever B is instantiated
will it be preinitialized for every object of B ?
Yes.Whenever you are creating object of B, A object is also created
either way is it a good practice ?
Practically it is the same as instantiating through a constructor. So no problems of being a good or bad practice
Then why do we have constructors if we can do this ?
If you have multiple constructors, then you don't have to instantiate A in every constructor.
Related
Consider we have classes like this:
class A {
public B b;
public void someFunc() { // called sometime
b = new B();
}
}
Class B's constructor assigns some inner variables.
Field b is not thread-safe in the sense another thread can view b not-null when B constructor hasn't finished. (during someFunc execution)
My question is the following: how can it be (from the logic perspective) that the constructor hasn't finished yet?
For me reordering of such kind is magic.
In the context of thread safety, this usually happens because of just-in-time (JIT) compilers. A JIT compiler takes Java byte code and translates it in to machine code to make it run faster. During translation, it's able to make a lot of optimizations, such as inlining various methods and constructors.
Supposing B had a constructor like this:
class B {
int x;
B(int x) { this.x = x; }
}
When a constructor is inlined, it takes Java code that's something like this:
b = new B(1);
And translates it to machine code that takes steps similar to the following:
Allocate space for a B object somehow.
Store the pointer to that memory in to b.
Store 1 in b.x.
In other words, code which is analogous to this (in terms of ordering):
b = new B();
b.x = 1;
But we don't actually call a constructor at all. We'd just allocate a B, however the JVM does it internally, and assign b.x directly. Calling the constructor would involve jump instructions, so it's a bit faster to inline it.
There's an example like that in the famous "Double-Checked Locking is Broken" Declaration.
A regular Java compiler would be allowed to inline constructors too, but regular Java compilers don't typically perform many optimizations.
Instance of object can "escape" from constructor, like that:
public class EscapeDemo {
static void escape(B b) {
System.out.println(b.strA);
System.out.println(b.strB); // still null in this example, even if field is final and initialized to non-null value.
}
public static void main(String[] args) {
System.out.println(new B());
}
}
class B {
final String strA;
final String strB;
B() {
strA = "some operations";
EscapeDemo.escape(this);
strB = "here";
}
}
prints:
some operations
null
B#hashcode
And in similar way that reference could escape to some code that will use it from other thread.
Like Andy Guibert added in comment: this is a bad practice to write such code - as it might be source of many weird errors and hard to trace bug - like here we have something that should not be a null, but it is a null.
And if you want to do something with object instance on creation it is much better idea to create static factory method that will create instance and then do something with (like add to some collection/registry) it and then return it.
Also if you include usage of weird code nad hacks - in bytecode java object creation is separated from constructor call, so it is possible from bytecode level to create an object, pass it somewhere and call constructor in some other place.
But otherwise field is assigned after right side expression is executed so for code
b = new B();
field b can be only null or B instance after constructor is called. Unless you would set that field from inside of B constructor like in my escape example.
If I understand your question correctly. You are asking about if you create an instance of Object A which has a field b of type B and the field b is not initialized when A is created but only some other object calls someFunc(). What will happen when some other thread tries to access this field b?
If so, when you create a new object of type B the JVM will allocate some memory for this object and then will return a reference which will be held in the field b. If other thread tries to access the field b before it got the reference of the new object, it will return null otherwise will return the reference to the newly created object.
I'm having confusion in calling a non-static method
class A {
void doThis() {}
public static void main(String... arg) {
A a1 = new A();
a1.doThis(); // method - 1
new A().doThis(); // method - 2
}
}
I know that both method-1 and method-2 will call doThis(), but is there any functional difference?
There won't be any difference in execution of those methods but in case of new A().doThis() your're going to lose the reference to the instance of an object you've invoked the method on and you won't be able to use it further in your code. All the changes this method could've done to internal state of the instance will be lost.
In case of A a1 = new A(); a1.doThis(); you're going to preserve the instance of an object (in variable a1) and potential changes made to its state made by method doThis(). Then you'll be able to continue working with this object.
Is there any functional difference?
Both will behave in the same way.
The second option doesn't allow you to reuse that instance again. It may be convenient and concise in one-line return statements (for instance, consider the builder pattern where each constructing method returns a half-initialised instance):
return new Builder().a().b().build();
or if an object was created only to perform a defined action once.
What will be the reference of a new object in method-2?
It is no longer exist (more precisely, we don't have access to it) unless the doThis returns this which you could be able to put in a variable after method execution.
Can I say that method-2 is an improper way of calling a non-static method?
No. Why should we create a variable if this variable will never be used afterwards?
Let's see what the code says in plain English:
A a1 = new A();
a1.doThis();
Create a new instance of A.
Store a reference to it in the variable a1.
Call doThis() on our instance.
Whereas new A().doThis(); reads as:
Create a new instance of A.
Call doThis() on our instance.
So the only difference is whether you store it in a local variable or not. If you don't use the value in the variable any more, then that difference doesn't matter. But if you want to call another method on the same object, let's say a1.doThat(), then you're in trouble with the second solution, as you haven't got a reference to the original instance any more.
Why would you want to use the same object? Because methods can change the internal state of the object, that's pretty much what being an object is about.
Lets take a look at both these methods one by one.
Method-1
A a1 = new A();
a1.doThis();
In method-1, you have a reference of newly created instance of A, i.e a1 and you can call as many methods on this instance of A using this reference a1. Basically you can reuse that particular instance of A by using its reference a1.
Method-2
new A().doThis();
However in method-2, you don't have any variable that stores the reference of your newly created instance of A. How will you refer to that particular instance of A if you have to call any other method on that particular instance of A ? You will not be able to re-use that instance of A if you create an instance using method-2 and you will lose that instance as soon as it is used.
case1:
A a1 = new A();
a1.doThis();
The above two line means object created and doThis(); executed but still object available in the heap memory.
case2:
new A().doThis();
A class object created and doThis(); executed after immediately GC(GarbageColletor) will activate to remove the A object from the heap memory bcz it's a non-referenced object and we can call this object as an anonymous object.
This question already has answers here:
Is there a difference in setting fields inside or outside the constructor?
(8 answers)
Closed 8 years ago.
This is probably a 'duplicate', but I'm not sure how to search for this question...
I am initializing a non-static member variable at the declaration line:
public class A
{
private B b = new B();
...
}
I am doing it instead of initializing this variable inside the default constructor:
public class A
{
private B b;
public A()
{
b = new B();
}
...
}
Is there any difference between the two, except (perhaps) the former not being "ANSI Java" or something like that?
I am getting two different byte-codes (i.e., two different 'class' files) for the two implementations above, which leads me to believe that there might be run-time differences.
So I would like to know if I have any reason to expect anything different during run-time.
Thanks
The first one is a declaration and initialization at the same time .
In the second example instead you have the declaration of the b variable not initialized and then in the constructor you initialize the variable ...
The functional difference can come at the moment that you add another constructor, in that case the b variable should be initialized even in that constructor or if not, there will be a huge difference .
In the first case you have the variable initialized no matter how many constructor you implement ...
Honestly I don't understand how can you pretend to have the same bytecode, writing two different things as for this case .
No different in general (mean that declare outside and inside a constructor will behave something different). Just remind that initialize outside will run first, before come into some specific constructor. For example:
class A {
int a = 3;
public A() {
a = 4; // now a = 4. not 3
}
}
But, I often use them with different purpose :
Initialize variables inside constructor make it clearer and help you initialize something more complex. for example, put some logic code, put a loop to add items, ... that you cannot do when initialize outside of constructor scope.
When you have many overloading constructors, and some variables always declare same. Simple "state variable" such as isExist isEmpty ... I often initialize outside of constructor scope. So, all other constructors don't do the same thing.
There are no difference, both codes work well. I personally prefer the second way for a big class, meanwhile the first is preferd for small classes.
There is one small difference between this approaches!
When variable is declared inside constructor, there is chance that after some time second constructor will be created and this variable will be uninitialized. For fighting this declare this variable as final - if this is possible of course ;)
Other differences not exists :)
public class A
{
private B b;
public A() {
b = new B();
}
public A(int value) { // second constructor
}
...
}
After using A a = new A(5); field b is null.
The main difference is the order of function calls:
In the 1st case, method B() is called before method A().
In the 2nd case, method A() is called before method B().
An additional difference is what has been suggested in all other answers...
When a non-default constructor which does not initialize variable b exists:
In the 1st case, variable b will be initialized even when that constructor is used.
In the 2nd case, variable b will not be initialized whenever that constructor is used.
for example, lets say you have:
class X
{
public void foo()
{
}
}
and then in your main you have
X anX = new X();
anX.foo();
X bX = new X();
bX.foo();
is the "foo" method being duplicated for every instance of X? Or is it that each instance just re-uses the foo method code.
It will reuse the method code for each object. What changes is the implicit argument, which is the object you invoke the method on.
Instance methods are despatched (more or less) using a Class pointer and an internal virtual-method table. Similar, but slightly more indirect & slower, for methods accessed via an interface.
Class VMTs and method code are loaded once per ClassLoader & then shared between all objects using the method. Thus class type information & method code are not duplicated in memory.
Objects always keeps their Class pointer and the (internal) virtual-method table. This applies whether casting to a subtype or assigning to a supertype. Object Class and the internal pointer are assigned at construction and invariant for the lifetime of the object.
Static methods OTOH are not virtualized, do not use a VMT & despatch according to the static type of the reference. This is resolved at compile time.
I have noticed in the code in my system that someone instantiated an anonymous class as follows
Class ExampleClass{
MyObj obj;
methodA(new ClassA(){
#override public void innerMethodA(){
//code...
}
});
}
So far so good.
Now, in order to use obj that was declared before the method I usually define it as final.
I don't really understand why but i do because the compiler asks.
In this code i see in innerMethodA() the usage of
ExampleClass.this.obj()
without final.
My questions :
1. why do I have to put final when I use obj?
2. what is ExampleClass.this ? Notice that ExampleClass is the Class not an instance. then what is the "this"? if it has several instances?
3. What happens if I change the obj while the inner method runs (in my code inner method runs in a loop so I plan on changing it . will it explode?)
You have to use final when you capture the variable of a local variable... not an instance variable of the enclosing class.
ExampleClass.this is a reference to the instance of ExampleClass associated with the instance of the subclass of ClassA. In your case, it will be the same as this within methodA.
It won't explode - it will just change the value of obj. Think of it as capturing the value of ExampleClass.this (so you can't change that) but you can change the data within the object referred to by ExampleClass.this.
There are no "true" closures (functions that capture scope) in Java. See e.g.http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-different
You can use this form to reference ambiguous methods / variables in the scope of "ExampleClass".
You cannot change the reference. What you can do is use an indirection, e.g. a final reference to an object that can swap it's values. An example would be the class of Atomic value holders, e.g. AtomicReference.
Because, the way you described it, in this case, they are not using ExampleClass.this.obj, they are calling the method ExampleClass.this.obj().
ExampleClass.this refers to the encapsulating instance of ExampleClass in which this ClassA instance is instantiated.
Not necessarily.