1

Lets say I have the following setup

an interface

public interface TestInterface {

  public void draw();
}

and two implementations

public class Square implements TestInterface {

  @Override
  public void draw() {
    System.out.println("Square");

  }

}

and

public class Circle implements TestInterface {

  @Override
  public void draw() {
    System.out.println("Circle");

  }

}

Now I can easily do

TestInterface a = new Square();
a.draw();

and I correctly get Square. Next, I wanted to try out reflection.

Class<?> clazz = null;
    try {
      clazz = Class.forName(className);
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    Constructor<?> constructor = null;
    try {
      constructor = clazz.getConstructor();
    } catch (NoSuchMethodException | SecurityException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }
    Object instance = null;
    try {
      instance = constructor.newInstance();
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
        | InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    Method method = null;
    try {
      method = instance.getClass().getMethod(methodName);
    } catch (NoSuchMethodException | SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    try {
      method.invoke(instance);
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

and for className as some.package.Square and methodName as draw I again get Square. Which is correct.

The problem is that my application has access to the interface but not the actual implementations. Hence I know which methods to invoke, but I have to specify the implemented classes as well and I dont know which package they may reside in. What if I only know the name of the class but not the package?

Is there a way where I can still use the initialization form of

TestInterface a = new <some_parameter>();
a.draw();

Is there a way to generalize it? Or is the approach using reflection that I showed above, the only way to achieve something like this? Lastly, would it make any difference if I used an abstract class instead of an interface?

AbtPst
  • 7,778
  • 17
  • 91
  • 172

2 Answers2

2

You need to pass:

@param      className   the fully qualified name of the desired class.

When you have for example three class with the Same name but in diferent packages

--package1
----Test
--package2
----Test
Main
Test

And in Main you have:

public static void main(String[] args) throws UnsupportedEncodingException {

        Class<?> clazz = null;
        try {
            clazz = Class.forName("Test");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

It will call the one that is level of Main. For calling the others you will need to pass the fully quallifed name.

    clazz = Class.forName("package1.Test");
    clazz = Class.forName("package2.Test");

What if I only know the name of the class but not the package? So you need to know in what level you want. Because as you know that different packages the classes can have same names. So which Class do you need if you have that issue.

Gatusko
  • 2,503
  • 1
  • 17
  • 25
0

You have to know the full name of the class. Only the name of the class is not enough to load it in the memory and to use it through reflection. However, you can determine the implementations of your interface using the reflections library.

Maybe this discussion thread can help you: How can I get a list of all the implementations of an interface programmatically in Java?

Octavian R.
  • 1,231
  • 8
  • 12