This question already has answers here:
Java order of Initialization and Instantiation
(2 answers)
Closed 3 years ago.
Exactly when the Class members are initialized ?
In below code:
public class A{
public B b = new B();
private C c = new C(123);
public A (arg a){
// Do something
}
public someMethod(){
Log.i(TAG, " "+ b.getD());
}
}
main(){
A a = new A ("xyz"); }
When would be the Object of Class B & C created? And is it guaranteed to be created?
Should a professional app use such code or not ?
You can analyze the question this way:
class Scratch {
public static void main(String[] args) {
A a = new A ("xyz");
}
}
class A{
public B b = new B();
private C c = new C(123);
public A (String a){
System.out.println("new A()");
}
}
class B {
public B() {
System.out.println("new B()");
}
}
class C {
public C(int i) {
System.out.println("new C()");
}
}
which executes giving the following output:
new B()
new C()
new A()
which matches wiith the answer of #Jakir Hossain.
So: inline fields initializers are executed before code in constructor, following the same order which they are declared in.
Instances of classes B and C are created on A's instance creation, before A's constructor is executed. This ordering (and fields' initialization) are guaranteed.
When an object is created, the following things are done in the following order:
The object is allocated on the heap with the correct object type,
and all instance fields are "default initialized" to zero, false or
null.
The expressions in the super(...) or this(...) are evaluated and the
constructor for the next class up the chain is called. (This
recurses up the chain constructor, so that the Object constructor
gets executed first.)
The instance variable initializers and any instance initializer
blocks are executed in order.
The body of the constructor is executed.
The constructor returns.
Hope it helps you.
Related
This question already has answers here:
Are fields initialized before constructor code is run in Java?
(5 answers)
Closed 2 years ago.
I'm trying to understand why the output of the following Java code is as like this:
class A {
public A() {
System.out.print("A()");
}
public static void main(String[] args) {
}
}
class B {
public B() {
System.out.print("B()");
}
public static void main(String[] args) {}
}
class C extends A {
B b = new B();
}
public class E05SimpleInheritance {
public static void main(String args[]) {
new C();
}
}
Output:
"A()B()"
I would imagine that when the main method of the E05SimpleInheritance public class is called the following things should happen
Non-public class C is loaded and its fields are initialized(before calling the default constructor of class C)
Since its member 'b' is an object of class B, class B is loaded in memory
Since we construct an object of Class B its constructor is called which should print B()
Default constructor of C is called which automatically calls the constructor of the superclass A which print A()
So the final output should be B()A() which is obviously wrong so I do not really understand how the code flows in this case. Can you perhaps show me why is A()B() printed instead of B()A()
Your mistake is in step 1:
Non-public class C is loaded and its fields are initialized(before calling the default constructor of class C)
This is not what’s happening. In reality, non-static fields are initialised at the beginning of the constructor, not before it. And the base class constructor is implicitly (or explicitly) invoked even before that.
In other words, javac generates code for C which is equivalent to the following:
class C extends A {
B b;
C() {
super();
b = new B();
}
}
This question already has answers here:
calling a function in a class's "owner" class
(8 answers)
Is there a way to access the variables of the calling class in a method?
(3 answers)
Closed 3 years ago.
An instance a of class A has an instance b of class B.
How can b access a variable of a?
class A {
boolean flag;
B b;
public static void main(String[] args) {
A a = new A();
}
public A() {
b = new B();
b.doSomething();
chageFlag();
b.doSomething();
}
void changeFlag() {
// do something with flag
}
// other stuff
}
class B {
void doSomething() {
// here I need to access a from the instance owning b.
boolean aFlag = ?? // how to access a.flag ??
}
}
You will not be able to access a variable of A in this instance because A and B have no parent/ child or outer/inner class relationship here.
The way to do this is to pass the instance of A to B, such as,
B b = new B(this);
For this you need to adjust the constructor to take in A as a parameter.
As your code is, b has no way of reaching a; simply because it does not have a reference to it.
If the two classes are so related that you need b to know about a, then you can make B an inner class in A:
class A {
boolean flag;
B b;
public static void main(String[] args) {
A a = new A();
}
public A() {
b = this.new B();
b.doSomething();
changeFlag();
b.doSomething();
}
void changeFlag() {
}
class B {
void doSomething() {
boolean aFlag = flag;
}
}
}
B.doSomething() is able to read flag from the enclosing class because B is an inner class.
Be aware that this solution is not appropriate in all situations, it makes the coupling between the two classes even tighter.
I wrote down this mini-program:
A class:
public class A
{
public A()
{
System.out.println(getS());
}
public String getS() { return s;}
}
B class:
public class B extends A
{
private String s = "hello2";
public String getS() { return s;}
}
main:
public static void main(String[] args)
{
B b = new B();
}
and it printed:
null
Why is that?
I know that the String that printed is B's string, but why it didn't initialized before?
According to this answer - the variable initialized before the constructor..
EDIT -
I edited the code so the unrelated code won't confuse
Here is what's going on: when you construct B, the first thing its constructor needs to do is constructing A. This is done before B's own field s is initialized.
A constructs its own s, and then calls getS. However, it does not get its own getS, because B provides an override for it. Recall that B.s has not been initialized yet. That is why you see null printed.
Follow-up reading: What's wrong with overridable method calls in constructors?
What is happening:
You create a B instance, this will call the super() so the constructor of A.
Here it will do the print using the getter getS(). This will use the getter of B since this is the type of this but in this getter, the String is not yet instanciate since it is still doing the super class construction, so it return null.
Note that the String s in A is hidden by the one in B
The order during an instance is :
the static (from the super then the class)
the super class declaration (statement then constructor)
the block statement
the constructor
As Seen with :
public class A{
static{System.out.println("sA");}
{System.out.println("A1");}
public Main() {
System.out.println("new A");
}
{System.out.println("A2");}
public static void main(String[] args) {
new A();
}
}
class B extends Main {
static{System.out.println("sB");}
{ System.out.println("B1"); }
public B() {
System.out.println("new B");
}
{ System.out.println("B2"); }
}
Output :
sA
sB
A1
A2
new A
B1
B2
new B
it prints null because you have polymorphism in java. You Overrided method getS(). So when you call it from A, you try to call getS() from class B. But you didn't create instance of class B yet, because you need to finish class A first. So String in class B haven't been initialized yet, because of it you get null.
Can someone please elaborate me in detail the following scenario, it would be more convenient if the explanation includes the memory allocation and its reference for the three cases :
How is the flow executed in the three cases ?
Why the flow differ in the three cases ?
Though there is a circular dependency between the two classes why the case 1 alone gets executed where as the remaining cases were failed ?
CASE ONE
namespace CircularDependency_1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("executed");
Console.ReadLine();
}
}
public class B
{
public static A a = new A();
public B()
{
Console.WriteLine("Creating B");
}
}
public class A
{
public static B b = new B();
public A()
{
Console.WriteLine("Creating A");
}
}
}
OUTPUT
Creating A
Creating B
Creating A
executed
CASE TWO
namespace CircularDependency_1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("executed");
Console.ReadLine();
}
}
public class B
{
public static A a;
public B()
{
a = new A();
Console.WriteLine("Creating B");
}
}
public class A
{
public static B b;
public A()
{
b = new B();
Console.WriteLine("Creating A");
}
}
}
OUTPUT
Process is terminated due to StackOverflowException.
CASE THREE
namespace CircularDependency_1
{
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("executed");
Console.ReadLine();
}
}
public class B
{
public A a;
public B()
{
a = new A();
Console.WriteLine("Creating B");
}
}
public class A
{
public B b;
public A()
{
b = new B();
Console.WriteLine("Creating A");
}
}
}
OUTPUT
Process is terminated due to StackOverflowException.
#Versatile, you are close, but not right. The reason why the first case executes and two other cases fail, is not just because the objects are created inside the constructor or inside the class (outside of the constructor). To prove this, try making the a and b fields not static in the B and A classes (Case one), respectively; and you will see that it will fail, even though the objects are created outside of the constructor.
Case 2 and 3 fail because of the reasons explained by #Versatile.
Case 1 executes because of static members.
Let's examine the flow:
In the Main method the line A a = new A() begins creating the a object. In this process, an object of class B will be created because of the line public static B b = new B() - this very line will start creating another object of the class A because of the line public static A a = new A() in the body of class B. Now, here comes the magic (that doesn't fire a circular dependency). This line, public static A a = new A() will start creating another object of class A, while creating this object it won't create another object of class B because it is a static member of A, and it was already created. As we know, static members of a class are shared among all instances of the class. Therefore, it won't trigger the creation of another object of class B. In total, we end up with three instances of the classes in the order : A, B, A.
UPDATE
It is interesting to observe, in the first case, what happens if we initialize the static member inside the constructor. Even though, the A and B classes declare static members, the execution will fail due to circular dependency. This is because the static members are not initialized before the constructor is executed.
1.How is the flow executed in the three cases ?
First the static void Main() gets called and then the constructor of object A is called because of code line A a = new A();
2.Why the flow differ in the three cases ?
3.Though there is a circular dependency between the two classes why the case 1 alone gets executed where as the remaining cases were failed ?
Both the above scenarios are observed for the same reason. If you look closely, you assign memory as follows.
Case1 in the class and not the constructor. i.e.
public class A
{
public static B b = new B();
}
Moreover the object is static so it will be created only once and as this is created once the memory which is assigned in the same line gets executed only once.
Case 2 and Case 3: Memory to Objects A and B is assigned in the constructor i.e. in constructor of A the memory is assigned to B and in constructor of B memory is assigned to A, which results in calling the respective class constructors again and again until it throws an exception.
I am facing a problem with the below program , it has two classes A and B and one method getObject() in Class A that has been overridden in class B, Class B extends Class A.
I am calling getObject() from the base class constructor which I believe it will call the overridden method in class B, and at runtime the error is null pointer exception, why the Object has not been initialized, even so it has?
class A {
Object object = new Object();
public A() {
System.out.println("A Class");
getObject();
}
public void getObject() {
System.out.println("Class A Version");
System.out.println(object.toString());
}
}
class B extends A {
Object object = new Object();
public B() {
System.out.println("B Class");
}
#Override
public void getObject() {
System.out.println("Class B Version");
System.out.println(object.toString());
}
}
public class Init {
public static void main(String[] args) {
new B();
}
}
output
A Class
Exception in thread "main" Class B Version
java.lang.NullPointerException
at net.mindview.util.B.getObject(Init.java:28)
at net.mindview.util.A.<init>(Init.java:8)
at net.mindview.util.B.<init>(Init.java:21)
at net.mindview.util.Init.main(Init.java:34)
According to this answer:
The correct order of initialisation is:
Static variable initialisers and static initialisation blocks, in textual order, if the class hasn't been previously initialised.
The super() call in the constructor, whether explicit or implicit.
Instance variable initialisers and instance initialisation blocks, in textual order.
Remaining body of constructor after super().
See sections §2.17.5-6 of the Java Virtual Machine Specification.
So basically, object in class B is not initialized yet during constructor of class A is being executed (point 2: implicit super() call).
Within B constructor you call A construct which is using B's getObject() which is using not initialized object from B.
Use debugger step by step and you will see the flow.
The NPE is coming from the class itself, not object. While the constructor is working, this is null.
B extends A, so there's an implicit super constructor call inserted. That prints your "A Class" line, but then the method call is equivalent to this.getObject();, and this is null.
I think the key point of this problem is that you should know that the constructor of super class (A in case) will be called first. let's assume antoher condition that A also extends C , in case, constructor of c will be called first.
so the order of call should be : 1 construtor of C, 2 constructor A and then constructor of B at the last.
For your case, because Constructor A was called first , at this point object is not initialized yet which cause the null pointer excetion
Execution orders are:
class A {
Object object = new Object(); // --------------- 2
public A() {
System.out.println("A Class"); // ---------- 3
getObject(); // ---------------------------- 4 (calls B.getObject())
}
public void getObject() {
System.out.println("Class A Version");
System.out.println(object.toString());
}
}
class B extends A {
Object object = new Object(); // --------------- 7 (not executed)
public B() {
System.out.println("B Class"); // ---------- 8 (not executed)
}
#Override
public void getObject() {
System.out.println("Class B Version"); // -- 5
System.out.println(object.toString()); // -- 6 (exception!)
}
}
public class Init {
public static void main(String[] args) {
new B(); // ------------------------------- 1
}
}
You should never call overridable method in constructors as it introduces ambiguity in terms of which method to call. In you case your super class A calls B's getObject(). At this Point B is yet not instantiated so the call fails and gives you NPE.