1

I have various classes with singleton pattern. They all are extending from an abstract class. Each class has a getInstance() method (with exact same name). I want to get instance with the class name (String). For example

public abstract class AbsCls {
}

public class A extends AbsCls {
  private static A a;
  private A() {
}
public synchronized static A getInstance() {
  if(a==null) {
    a == new A();
  }
  return a;
}

public class Test {
  public static void main(String[] args) {
    AbsCls[] array = new AbsCls[5];
    array[0]=neededFunction("A");
    array[1]=neededFunction("B");
  }
}

All the classes have the same structure with class A. How should be the neededFunction()?

I can write "if.. else", but i feel like there should be a more elegant way. Thanks for any help in advance...

1
  • I would recommend you to read about and implement the Visitor design pattern Commented Nov 18, 2013 at 16:21

2 Answers 2

1

You could use the full class name as in package.ClassName, reflection, and Class.forName(theName).

For instance with a String object:

try {
    String newString = (String)Class.forName("java.lang.String").newInstance();
}
catch (IllegalAccessException iae) {
    // TODO handle
}
catch (InstantiationException ie) {
    // TODO handle
}
catch (ClassNotFoundException cnfe) {
    // TODO handle
}

So your method could roughly look like:

@SuppressWarnings("unchecked")
public static <T> T getInstance(String clazz) {
    // TODO check for clazz null
    try {
        return (T)Class.forName(clazz).getMethod("getInstance", (Class<?>[])null).invoke(null, (Object[])null);
    }
    catch (ClassNotFoundException cnfe) {
        // TODO handle
        return null;
    }
    catch (NoSuchMethodException nsme) {
        // TODO handle
        return null;
    }
    catch (InvocationTargetException ite) {
        // TODO handle
        return null;
    }
    catch (IllegalAccessException iae) {
        // TODO handle
        return null;
    }
}

Edit for OP:

The (Class<?>[])null and (Object[])null are null arguments cast as their expected type.

Basically:

  • the getMethod method of Class takes a String representing the method's name, and a varargs of Class<?> representing its parameter types. The method we call (getInstance) takes no arguments, therefore the argument to getMethod is null, but we want to cast it as the expected argument. More info here.
  • the invoke method of Method takes an Object as the target instance to invoke the method against (in our case, null since it's a class method) and a varargs of Object as the arguments. But again, your getInstance method takes no arguments, so we use null and cast it as an array of Object. More info here.
Sign up to request clarification or add additional context in comments.

3 Comments

But because of the singleton pattern, constructors of A, B, C... classes are private. So newInstance() method does not work. I use A.getInstance() to create an object...
It did the trick. Thanks a lot. But if you can explain "(Class<?>[])null" and "(Object[])null" when you have time, it'ld be appreciated...
@s.alem You're welcome :) I will comment on those parameters in my answer.
0
AbsCls[] array = new AbsCls[5]; // this create object for AbsCls
 array[0]=neededFunction("A"); // calling method from AbsCls
array[1]=neededFunction("B");// calling method from AbsCls

If you create object for super class you cant get method from sub classes

 AbsCls[] array = new A[5]; //this create object for A

You access both classes if you want to call super class method user super keyword

    array[0]=neededFunction("A"); //// calling method from A
    array[1]=super.neededFunction("B");//// calling method from AbsCls

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.