Why the flow of execution of the following cases was different? - java

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.

Related

What happend will subClass and SuperClass have same attributes in Java?

public class Test {
public static void main(String[] args) {
B b = new B();
b.test();
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
why the cant input out "b"?
i just think b.test() will call method of superClass, so b will user superClass's attribute.
why the cant input out "b"? i just think b.test() will call method of superClass, so b will user superClass's attribute.
Java class and instance variables can be inherited, but they are not virtual. That is, all variable identifiers appearing in Java code are resolved at compile time -- there is no dynamic resolution for them.
Thus, the appearance of identifier aString in method A.test() is resolved at compile time to the aString attribute of class A. This is the attribute that all invocations of that method will access, regardless of the actual class of the object on which it is invoked. If you want to use the attribute of class B when test() is invoked on an instance of that class then provide getter methods in classes A and B and have A.test() obtain the string via those.
The variable in b is hiding the variable in a. You can fix it by removing the type in b
class B extends A {
public B () {
aString = "b";
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
Creates 2 aString variables for B. While A will not know about B extending it, B can always access "things" from its parent class A, using the super keyword. So when you are in B, you can use aString and super.aString and they will refer the 2 different variables:
class Ideone {
public static void main (String[] args) {
A a=new A();
B b=new B();
a.test();
b.test();
b.suptest();
}
static class A {
String aString="A.aString set from A";
void test() {
System.out.println("A.test(): "+aString);
}
}
static class B extends A {
String aString="B.aString set from B";
{
super.aString="A.aString set from B";
}
void test() {
System.out.println("B.test(): "+aString);
}
void suptest() {
System.out.print("B.suptest() calling super.test(): ");
super.test();
}
}
}
You can try it on IdeOne, produces output
A.test(): A.aString set from A
B.test(): B.aString set from B
B.suptest() calling super.test(): A.test(): A.aString set from B
Where the first two lines show nothing fancy, A.aString and B.aString both contain their initial value.
But the third output line shows that super.test() call in B really "ends" in A.test(), and that the initializer block in B really altered the inherited aString field.
(Side note: the static class magic relates to the example being contained in a single file, it doesn't affect the inheritance-part)
You are correct.
Since Class A and the method test() are not abstract and the fact that the method test() was not overrided by its subClass B, the return will be exactly how was specified in Class A even if you call it from a B instance.

When does the members of the class initialize? [duplicate]

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.

When does the constructor initiallize?

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.

Assign on declaration or assign in the constrctor?

is there a diffrence between this :
public class A {
B b;
A() {
b=new B();
}
}
and this :
public class A {
B b=new B();
A() {
}
}
if there is, what is it? and what is better practice?
if there is no, whats recommanded?
As far as i know there is no difference as long as you only have one constructor. If you have more than one constructor you will need to make sure it's assigned in all constructors. For that reason i would recommend the second approach.
The constructor runs after the instance variables are initialized, so there is a difference. It doesn't matter in a small example, but it can matter with more complex code. (Note, the order of the code doesn't matter. If the initialization is in the constructor, it runs second.)
The second approach is more convenient, so I tend to start with it. The first approach can be more useful though (for Inversion of Control and Polymorphism), so it often gets used in "real" code.
class B {
B() {
System.out.println("B constructor");
}
}
public class A {
B b=new B();
A() {
System.out.println("A constructor");
}
public static void main(String[] args) {
new A();
}
}
Output:
B constructor
A constructor
....
class B {
B() {
System.out.println("B constructor");
}
}
public class A {
B b;
A() {
System.out.println("A constructor");
b=new B();
}
public static void main(String[] args) {
new A();
}
}
Output:
A constructor
B constructor
Big Difference between them.
In first option Class B only instantiate when constructor without parameter is called. If you put and call any parametrized constructor Class B will not instantiate.
But in case of second option Class B will always instantiate regardless of any constructor call.

I need an explanation of when to use class variables?

Suppose we have a class like:
public class test {
int a=1;
static int b=1;
public int getA()
{
return a;
}
public void incrementA()
{
a++;
}
public void incrementB()
{
b++;
}
public int getB()
{
return b;
}
}
and I have a class with main method like this
public class testmain {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
test t= new test();
t.incrementA();
test t1= new test();
test t2= new test();
t2.incrementB();
test t3 = new test();
test t4= new test();
t4.incrementB();
System.out.println("t= "+t.getA());
System.out.println("t1= "+t1.getA());
System.out.println("t4= "+t4.getB());
System.out.println("t3= "+t3.getB());
System.out.println("t2= "+t2.getB());
}
}
I need the explanation about why t and t1 have different value of a, and all t2, t3, t4 have the same value of b. I know that I have declared b as static and all objects access the same address of that variable b. Why it is not causing any problem for a variable when each object it has its own a, now my question is since all the objects look to the same location in memory then why is a different value of each object?
Every object has its own exemplar of a. So there are as many a's as objects
Class (static) variable value will be accessible multiple instances of the class, In this case t...t4.
When you change 'b' using t.b (or) t4.b (or) test.b (or) using any methods of t..t4--> same 'b' value will be updated, becuase only one copy of 'b' exists across these.
Instance variable is specific to that instance. 'a' exists a copy for each instance t...t4.
Read this link for more details.

Categories