Suppose there are three classes namely A, B and C such that B extends A, C extends B.
Requirement is that client code should be able to call the constructors of each class only once successfully. Upon trying to call constructor twice it should throw an exception.
How can I implement this in Java if duplication of code is not permitted in the child classes?
Example :
public class A {
private static A instance;
public A() {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public class B extends A {
private static B instance;
public B() {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public class C extends B {
private static C instance;
public C() {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public class Driver {
public static void main(String[] args) {
A a1 = new A();
B b1 = new B(); //throwing IllegalArgumentException, it should not throw
}
}
Things I tried.
Maintaining a private static reference of the respective class type which is initially set as null.
In the constructor block I added a null check to assign this reference to the static reference. Did not work as I could not avoid duplicating code.
Requirement
//this should work fine
A a1 = new A();
B b1 = new B();
C c1 = new C();
---------------
//this should throw runtime exception
A a1 = new A();
A a2 = new A();
B b1 = new B();
---------------
//this should throw runtime exception
A a1 = new A();
B b1 = new B();
B b2 = new B();
---------------
//this should throw runtime exception
A a1 = new A();
B b1 = new B();
C c1 = new C();
C c2 = new C();
I hope I am clear with the requirements
Problem
We have established that the subclass implicitly calls the super constructor, which in return throws.
1. Singleton / Factory Method solution
What you want to achieve is described as a Singleton design pattern. It conceptually requires a static members.
Static fields and/or methods (if you want to use a factory method) are not inherited, so duplication of the code which manipulates the static field is inevitable.
You should use the duplicated null-check & store static instance technique, it is widely used and accepted. The amount of code duplication is minimal and you should not be scared of it.
EDITED as to implicit super constructor call: You can use a condition (as in A) or a factory method (as in B).
public class A {
private static A instance;
public A() {
if (this.getClass() == A.class) {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
}
public class B extends A {
private static B instance;
private B() { }
public static B getInstance() {
if (instance != null) {
throw new IllegalArgumentException();
}
return instance = new B();
}
}
public class C extends B {
private static C instance;
public C() {
// check if (this.getClass() == B.class) when someone extends C
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public static void main(String[] args) {
A a1 = new A();
B b1 = B.getInstance();
C c1 = new C();
}
Alternatively, you can declare a private constructor and have a static Factory Method. If you are in a multi-threaded environment, pay attention to synchronisation.
2. Collecting all instances in the top-most parent
An other obscure solution would be to collect all Class<> instances in the top parent and check for duplicity in the constructor. This is not a good conventional solution. The singelton pattern is usual.
public class TopClass {
private static final Set<Class<? extends TopClass>> instances = new HashSet<>();
public TopClass() {
if (instances.contains(this.getClass())) {
throw new IllegalArgumentException();
}
instances.add(this.getClass());
}
}
public class SubClass extends TopClass {}
public class AnotherClass extends SubClass {}
This way you limit all future subclasses to be instantiated only once. It is limiting, but yes - less lines of code.
I suppose you can make a Set of already initialized classes and check it every time you construct a new one. It allows create one instance of A, one instance of B and one instance of C.
class A {
private static final Set<Class<? extends A>> calledInitializations = new HashSet<>();
A() {
checkForSecondInit(A.class);
}
protected void checkForSecondInit(Class<? extends A> clazz) {
if (isNotInSuperClassOf(clazz)) {
if (calledInitializations.contains(clazz)) {
throw new RuntimeException("Second init in " + clazz.getName());
} else {
calledInitializations.add(clazz);
}
}
}
private boolean isNotInSuperClassOf(Class<? extends A> clazz) {
return getClass() == clazz;
}
}
class B extends A {
B() {
checkForSecondInit(B.class);
}
}
class C extends B {
C() {
checkForSecondInit(C.class);
}
}
We can create static Set collection and add the classname along with package to set. For new object, it will check if there is a existing class name in the set or not.
For thread safety,set is added in synchronized block.
import java.util.HashSet;
import java.util.Set;
public class A {
static Set<String> set;
public A(){
if(set==null){
synchronized(set){
set = new HashSet<>();
}
}
String classWithPackage = getClass().toString().split(" ")[1];
if(set.contains(classWithPackage)){
throw new RuntimeException("Only one instance can be created for: "+classWithPackage);
}else {
synchronized(set){
set.add(classWithPackage);
}
}
}
}
class B extends A{
public B(){
super();
}
public static void main(String[] args) {
A a = new A();
A a2 = new B();
B b1 = new B();
}
}
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.
}
}
Consider following situation. I want to achieve the different behavior for methoddA() of class A depending upon from where it is getting call like here from class D or class C. How this can be achieved, method overriding is not working here.
class A
{
public methodA(){ //some code }
}
class B
{
A a = new A()
public methodB()
{
a.methodA();
}
}
class C
{
B b = new B();
public methodC()
{
b.methodB();
}
}
class D
{
B b = new B();
public methodD()
{
b.methodB();
}
}
What you need here is Polymorphism. First create an interface -
public interface MyInterface
{
void methodA();
}
then create two different implementations for two different behaviors -
public class First implements MyInterface
{
public void methodA() {
// first behavior
}
}
public class Second implements MyInterface
{
public void methodA() {
// second behavior
}
}
Now create your other classes as follows -
class B
{
public void methodB(MyInterface m)
{
m.methodA();
}
}
class C
{
B b = new B();
public void methodC()
{
// Pass the corresponding behavior implementation
// as argument here.
b.methodB(new First());
}
}
class D
{
B b = new B();
public void methodD()
{
// Pass the second behavior implementation.
b.methodB(new Second());
}
}
This will result in a more maintainable code.
You can pass the class name to your method as a String and in your method check
if(className.equals("A") // or use isInstanceOf() if you are passing objects of A/B
//do something
if(className.equals("B")
// do something else.
Why do you need two different implementations?
This easy trick can work for you... Please correct me if i am wrong..
I following code I have modified the method signature of Class A1 and Class B1 to accept Object and similarly while calling the methods from Class C and Class D whereever we are calling this method of class B1 pass this as reference. In Class A1 we can then check instanceof object and identify the calling class.
class A1
{
public void methodA(Object c){ //some code }
if (D.class.isInstance(c)){
System.out.println("Called from Class D");
}else if (C.class.isInstance(c)){
System.out.println("Called from Class c");
}else{
System.out.println("Called from Some diff class");
}
}
}
class B1
{
A1 a = new A1();
public void methodB(Object c)
{
a.methodA(c);
}
}
class C
{
B1 b = new B1();
public void methodC()
{
b.methodB(this);
}
}
class D
{
B1 b = new B1();
public void methodD()
{
b.methodB(this);
}
}
public class Testnew{
public static void main(String args[]){
D d = new D();
d.methodD();
C c = new C();
c.methodC();
B1 b = new B1();
b.methodB(b);
}
}
Assume I have 4 classes: A, B, SA and SB where B extends A
and SB extends SA.
Class A has the following constructor:
private SA a;
public A() {
a = new SA();
}
Obviously when I'm calling the contructor for class B and since B extends A
constructor of class A is also called. But in such a case I would like the
constructor of A to do a = new SB(); instead of a = new SA();.
Is there an easy way to do this without
changing the public interfaces of both A and B?
Just have a public constructor and a protected constructor:
private SA a;
public A() {
this(new SA());
}
protected A(final SA a) {
this.a = a;
}
Then in B:
public B() {
super(new SB());
}
Yes it is. For example :
public A(YourEnum en) {
if (en == YourEnum.SA){
a = new SA();
} else {
a = new SB();
}
}
Also, depends on what you really need, it can be done by overloading constructors
public A(){
a = new SA();
}
public A(YourObjectYouNeed dataNeededForAnotherConstructor){
//doing initialization stuff
a = new SB();
}
I am new to java programming,I have one class,for this class i created two object(obj1,obj2).i don't want to create other than these object,if any body wants to create one more object for this class that should refer to first,or second objects only(instead of creating one more object).how to do this?please refer below code
class B
{
void mymethod()
{
System.out.println("B class method");
}
}
class Myclass extends B
{
public static void main(String s[])
{
B obj1=new B();//this is obj1
B obj2=new B();//this is obj1
B obj3=new B();//don't allow to create this and refer this to obj1 or obj2
}
}
Thanks
azam
Check out the Singleton design pattern.
What you need is the Singleton design pattern.
Class B should look something like so:
class B
{
private static B instance = null;
private B()
{
//Do any other initialization here
}
public static B getInstance()
{
if (instance == null)
{
instance = new B();
}
return instance;
}
}
Then, in your Myclass, just do this:
B obj1 = B.getInstance();
B obj2 = B.getInstance();
Note: This is not thread safe. If you are looking for a thread safe solution please consult the Wiki Page.
EDIT: You could also have a static initializer
class B
{
private static B instance = null;
static
{
instance = new B();
}
private B()
{
//Do any other initialization here
}
public static B getInstance()
{
return instance;
}
}
Yeah singleton it seems the correct way consider the info your providing here.
The default singleton implementation would be the following:
public class Singleton {
//holds single instance reference
private static Singleton instance = null;
//private constructor to avoid clients to call new on it
private Singleton()
{}
public static Singleton getInstance()
{
if(null == instance)
{
instance = new Singleton();
}
return instance;
}
}
Now you can get the single instance of the object by calling :
Singleton instance = Singleton.getInstance();
Keep in mind though that if your working on a threaded enviroment, singleton by default is not thread-safe.
You should make the getInstance method synchronized to avoid unexpected returns.
public synchronized static Singleton getInstance()
{
if(null == instance)
{
instance = new Singleton();
}
return instance;
}
Cheers
Generally speaking you need a singleton pattern. You need to make the constructor to become a private method. Then you create a method to instantiate class B, hence class B can only be instantiated by this method. Have a look at the singleton pattern. It is what you want I believe.
create singleton Class, like
public Class A {
private static Class a = new A();
public A getA() {
return a;
}
}
Object of class A has already created in class A itself. You don't need to create it outside. Just use getA() method to retieve the class A's object.
Like :
A objA = A.getA();
This is called Singlton Pattern.
You can use a Singleton. You have 2 possiblilities for that.
1 . Lazy Creation (Here you make the instance when call the function getInstance() and you check if the instance already exists):
class B {
static private B instance;
private void mymethod() {
System.out.println("B class method");
}
static public B getInstance() {
if (instance == null) {
instance = new B();
}
return instance;
}
}
class Myclass extends B {
public static void main(String s[]) {
B obj1 = B.getInstance(); // this is obj1
B obj2 = B.getInstance();
}
}
2 . Eager creation (Here you make the instance when the Class is called for the first time):
class B {
static private B instance = new B();
private void mymethod() {
System.out.println("B class method");
}
static public B getInstance() {
return instance;
}
}
class Myclass extends B {
public static void main(String s[]) {
B obj1 = B.getInstance(); // this is obj1
B obj2 = B.getInstance();
}
}
be aware, that using a singleton is a big restriction to your code. It can be very annoying when it's not possible to instance more than one object.
Especially when you dont have acces to the source....
The Effective way in multi threaded application, the below logic will may help
public class Singleton {
private static volatile Singleton _instance;
private Singleton(){}
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
I suppose people have not understood the problem statement. It says, not more than 2 objects shall be created. Singleton creates a single object and blocks any further instantiation.
maintain a static variable in ur object class, incrementing by 1 to the upper limit of objects while creating object
when object > bounds needs to be created, select a random number in range[1,bound] and return that object.
how to initialize a private static member of a class in java.
trying the following:
public class A {
private static B b = null;
public A() {
if (b == null)
b = new B();
}
void f1() {
b.func();
}
}
but on creating a second object of the class A and then calling f1(), i get a null pointer exception.
The preferred ways to initialize static members are either (as mentioned before)
private static final B a = new B(); // consider making it final too
or for more complex initialization code you could use a static initializer block:
private static final B a;
static {
a = new B();
}
Your code should work. Are you sure you are posting your exact code?
You could also initialize it more directly :
public class A {
private static B b = new B();
A() {
}
void f1() {
b.func();
}
}