0

I have several classes in the same package in Java. I want to instantiate objects of these classes from an array that has the class names as strings.

Here is an example of a class I would like to use, they all have the same structure.

class Class1 {

    public String[] firstMethod(){
        String[] data = {"NEW_ITEM"};
        return data;
    }
}

Here is the class I am attemtempting to instantiate them from.

class Main {

    static {
        String[] classes = {"Class1","Class2"};
        for (String cls : classes) {
            try {
                Object o = Class.forName(cls).newInstance();
                o.firstMethod();
            } catch(ClassNotFoundException | IllegalAccessException | InstantiationException ex) {
                System.out.println(ex.toString());
    }
}

My problem is that when I try to call firstMethod() using the object o, I am getting this error.

exit status 1
Main.java:19: error: cannot find symbol
    o.firstMethod();
     ^
symbol:   method firstMethod()
location: variable o of type Object
1 error

I suspect that it is because it is of type Object and not type Class1. I have seen solutions where you typecast the object to the object of the class that you need. However when you typcast, you need to use the name of the class, which is exactly what I am trying to avoid. I need to use the class name as a string.

Does anyone know of a solution where I can call methods with the objects that are created?

J.Dor
  • 1
  • 2
  • 1
    continue using reflection like `Method.invoke()` - use `getMethod` or `getDeclaredMethod` of the class to get the method, call `invoke` on it, passing the created instance as parameter - e.g. https://stackoverflow.com/q/160970/85421 – user85421 Nov 23 '18 at 21:53
  • 1
    I assume that these classes have something in common, generally speaking they implement some kind of interface. In this case you can simply cast to the interface and call that method. If this is not possible, you have to invoke the methods via reflection as well. – Glains Nov 23 '18 at 21:53
  • Carlos Heuberger, thanks for helping a noob. Method method = o.getClass().getDeclaredMethod("firstMethod"); method.invoke(o); I got it working with this. – J.Dor Nov 23 '18 at 22:01
  • in case the method is private you can use the method.setAccessible(true); – nmorenor Nov 23 '18 at 23:39

1 Answers1

0

You can't call your method the way in your code because you have an object which does not know the type Class1. You need to cast it explicitly like

((Class1)o).firstMethod()

which I don't think this is what you want.

Or, you can iterate through object methods and invoke it dynamically like below:

String[] classes = {"com.yourpackage.Class1", "com.yourpackage.Class2"};
for (String cls : classes) {
    try {
        Object o = Class.forName(cls).newInstance();

        for(Method m : o.getClass().getMethods()) {
            System.out.println(m.getName());
            if ("firstMethod".equals(m.getName())) {
                String[] data = (String[])m.invoke(o, null); // here are the parameters
                for(String d : data){
                    System.out.println(d);
                }
            }
        }

    } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ex) {
        System.out.println(ex.toString());
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

The output is :

NEW_ITEM
Emre Savcı
  • 3,034
  • 2
  • 16
  • 25