简体   繁体   中英

Calling methods from different classes with the class name

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...

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 .
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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM