3

This is a follow up on this question: Create new class from a Variable in Java

I want to load a class based on a string variable which works, but I can't call any methods of it.

I have multiple classes that all implement the same interface, e.g.

class Foo implements Bar {
    private String username = null;

    public String getUsername() {
        return this.username;
    }
}

Now I want to instantiate the class without knowing which one it is, then call getUsername() on it.

String a = "Foo";
Class<?> c = Class.forName(a);
Object object = c.newInstance();
System.out.println(object.getUsername());

This results in

Error:(74, 15) java: cannot find symbol

symbol: method getUser()

location: variable object of type java.lang.Object

If I cast it to the class like

Foo foo = (Foo) object;

it works, but I can't do that as I don't know the class' name.

Is there a way to do this or is this altogether a falsy attempt?

Community
  • 1
  • 1
baao
  • 71,625
  • 17
  • 143
  • 203
  • 1
    How do you know that getUsername() should exist ? Is it from an interface or abstract class that you know your instance will implement/extends ? – AxelH May 18 '16 at 13:19
  • Yes, it is known as they all implement a interface @AxelH – baao May 18 '16 at 13:20
  • If you are unable to cast the object you retrieved by `c.newinstance()`, then you have to use reflection to get the method `getUsername()`. – Turing85 May 18 '16 at 13:20
  • @mmm if all of your objects implement a common interface (which I assume defines `getUsername()`), why do you refuse to cast the object into the interface-type? – Turing85 May 18 '16 at 13:21
  • 1
    Then cast it into the interface type ;) – AxelH May 18 '16 at 13:22
  • Yeah, now I got it.. Thanks @AxelH – baao May 18 '16 at 13:22
  • 2
    Just a tips, use the annotation Override if you override or implements a methods, with it, you KNOW that this is from a parent class. – AxelH May 18 '16 at 13:25
  • I've just started reading about annotations, thank you for the hint, I'll have a deeper look into it.@AxelH – baao May 18 '16 at 13:26
  • I've had a complet answer to check if the cast is possible, don't hesitated to accept the answe if this work for you. – AxelH May 18 '16 at 13:35

3 Answers3

3

You should cast it to your interface: Bar object = (Bar) c.newInstance()

Nikem
  • 5,716
  • 3
  • 32
  • 59
  • You don't now the class name. But you have to now your interface. Without that, you cannot call any method. – Nikem May 18 '16 at 13:19
2

Just to be a bit more secure, you can check if the cast is possible.

public static void main(String arg[]) throws Exception {
    String a = "Test";
    Class<?> c = Class.forName(a);
    if(ITest.class.isAssignableFrom(c)){
        ITest object = (ITest) c.newInstance();
        System.out.println(object.sayHello());
    } else {
        System.out.println("Good bye");
    }
}

The interface is :

public interface ITest {
    public String sayHello();
}

And the class is :

public class Test implements ITest{

    @Override
    public String sayHello(){
        return "Hello World";
    }
}

This will check if the cast is possible by checking if the generated class is as a hierarchic link with the interface. This could be done with a try catch but this is prettier ;)

AxelH
  • 14,325
  • 2
  • 25
  • 55
0

You can try to use reflection using the class variable and the instance you created.

Method method = c.getMethod("getUsername");
method.invoke(object);

Docs: https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getMethod(java.lang.String,%20java.lang.Class...)

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)

SamTebbs33
  • 5,507
  • 3
  • 22
  • 44