How do I create only one object of parent and child

Tags:



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.

Answer

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.



Source: stackoverflow