I have written a piece of code as below.
that gives error instead of printing SUCCESS.
class A
{
{
new B();
}
static class B
{
{
new A().new C();
}
}
class C
{
{
System.out.println("SUCCESS");
}
}
}
public class Main
{
public static void main(String[] args)
{
new A();
}
}
Please help me where it fails.
You got an infinite chain of constructor calls that starts with new A();, which
creates an instance of A, which creates an instance of B (due to new B(); in the instance initializer block of class A), which creates another instance of A (due to new A().new C(); in the instance initializer block of class B), which creates another instance of B, and so on...
This leads to StackOverflowError.
The instance of C is never created, which is why System.out.println("SUCCESS"); is never executed.
Related
Design a class such that only one instance of the class and any of its sub-classes can be created. To clarify: Assume A is such a class and B is derived from A. B does not have any special code apart from extending A.
class A {
// code of class A
}
public class B extends A{
public static void main(String[] args)
{
new A(); // works fine.
new A(); // causes an exception
new B(); // works fine as this is the first instance of B
new B(); // causes an exception.
}
}
But we need to create the object with the new keyword.
I try in static value define in parent but this does not help.
class A {
private static Map<Class<? extends A>, A> instances = new HashMap<>();
public A() {
synchronized (A.class) {
if (instances.containsKey(this.getClass())) {
throw new IllegalStateException();
}
instances.put(getClass(), this);
}
}
// code of class A
}
public class B extends A {
public static void main(String[] args) {
new A(); // works fine.
new A(); // causes an exception
new B(); // works fine as this is the first instance of B
new B(); // causes an exception.
}
}
When you create an instance of A or any subclass of A, the constructor of A it is called.
The constructor checks if an instance of A is present in the Map instances.
If an instance of the current class exists, an exception is thrown.
If no instance of the current class exists (when no exception is thrown), the current object is saved to instances.
The Map is static so the same Map is used across all instances (It obviously would not work if every instance of A had its own Map).
The synchronized block makes sure that the map access is thread safe by locking the Class object of A. Locking the current Class object is not thread safe as the put method of HashMap is not thread safe when creating new objects.
You can also lock instances or use a Set of Classes as described in this answer from oleg.cherednik.
class A {
private static final Set<Class<? extends A>> INSTANCES = new HashSet<>();
public A() {
synchronized (INSTANCES) {
if (INSTANCES.contains(getClass()))
throw new RuntimeException("duplication: " + getClass().getSimpleName());
INSTANCES.add(getClass());
}
}
// code of class A
}
class B extends A {
public static void main(String[] args) {
new A(); // works fine.
new A(); // causes an exception
new B(); // works fine as this is the first instance of B
new B(); // causes an exception.
}
}
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'm reviewing for a certification exam and I experimented with the following codes:
class A {
B b = new B();
static {
System.out.println("A static.");
}
{
System.out.println("A instance.");
}
A() {
System.out.println("A constructor.");
}
}
class B extends A {
static {
System.out.println("B static.");
}
{
System.out.println("B instance.");
}
B() {
System.out.println("B constructor.");
}
}
public class Raaawrrr {
public static void main(String args[]) {
A a = new A();
}
}
It prints:
A static.
B static.
and causes a stack overflow afterwards. I'm having a hard time understanding why. Would you be able to help me out?
A instantiates B. B happens to also be of type A, so that gets instantiated again. Which instantiates B... and so forth.
You are creating an object of class B which is sub-class of A in class A. Note that the constructor of super-classes must be executed before the execution of sub-class constructor.
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.
Consider the following code classes.
public class A
{
public A()
{
callCreation();
}
protected void callCreation()
{
System.out.println("A Created!!");
}
}
public class B extends A
{
protected void callCreation()
{
System.out.println("B Created!!");
}
}
public class C extends B
{
protected void callCreation()
{
System.out.println("C Created!!");
}
public static void main(String[] args)
{
A a = new A();
A b = new B();
A c = new C();
}
}
The output of running the class C is given below.
A Created!!
B Created!!
C Created!!
The first output line in the output A Created!! is printed because when the constructor of class A is called, it calls the super class's constructor (java.lang.Object) implicitly before calling the callCreation() method in the class A's constructor. And this will be the case for B and C classes too. In that case when the constructor of B is called the call flow should be typically : B's constructor -> A's Constructor -> java.lang.Object's Constructor -> come back to A's callCreation() method to finish calling A's constructor. If so how is the overridden value printed and not the super class's value is printed? So the question is 'when is an object of a class created exactly? to put it in other words, the object of a class should be created only after the constructor finishes calling/initializing all the elements within itself. If so how can a method be called from a child class and not from the parent class?
The callCreation methods in B and C override the method from A. So when the method is called in the constructor A the implementations in B and C will be run, even though the constructors of B and C have not been executed yet. This is possible because constructors don't actually create the object, rather they are called to initialize some moments after the JVM has created it.
In general it's a very bad idea to call methods that can be overridden from a constructor for this very reason. A method in B or C may assume that the constructor and object initializers have already been run, and read an unexpected value from a field. For example the following ends up printing "B Created!! null" because the field still has not be assigned its value.
public class B extends A
{
final String msg = "Yes!";
protected void callCreation()
{
System.out.println("B Created!! "+msg);
}
}
thinking in this way makes it more obvious:
when an object of type B is being created super() keyword calls the A constructor,
then in A constructor "this.callCreation()" is executed, which refers to the current
object which is B, so callCreation corresponding to the current object(B) is called.
the same process is done for C.
public class A {
public A() {
this.callCreation();
}
protected void callCreation() {
System.out.println("A Created!!");
}
}
class B extends A {
public B() {
super();
}
protected void callCreation() {
System.out.println("B Created!!");
}
}
class C extends B {
public C() {
super();
}
protected void callCreation() {
System.out.println("C Created!!");
}
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
}
}