迭代类的映射并调用

时间:2016-03-31 14:13:52

标签: java dynamic abstract-class

这里的invoke()错误:java.lang.ClassNotFoundException: class HelloWorld$Foo,我不清楚为什么。我还不得不求助于获取字符串.class.toString(),而不是直接使用.class

您是否可以帮助我调用该方法,如果还不能避免toString()调用?

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

public class HelloWorld{

    public static void main(String []args){
        Map<String, Class> myMap = new HashMap<String, Class>();
        myMap.put("foo", Foo.class);
        myMap.put("bar", Bar.class);

        try {
            for(String name : myMap.keySet()){
                Class<?> clazz = Class.forName(myMap.get(name).toString()); // do I need to go through string at all?
                Object foobar = clazz.newInstance();
                System.out.println("name: " + name + " goes " + foobar.getClass().getMethod("chirp").invoke(foobar));
            }
        } catch (Throwable e) {
            System.err.println(e);
        }
    }
    public abstract class Foobar {
        abstract String chirp();
    }
    public class Foo extends Foobar {
        public String chirp () { return "chirp-chirp!"; }
    }
    public class Bar extends Foobar {
        public String chirp() {return "woof-woof!"; }
    }
}

编辑:完成答案:

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

public class HelloWorld{

    public static void main(String []args){
        Map<String, Class> myMap = new HashMap<String, Class>();
        myMap.put("foo", Foo.class);
        myMap.put("bar", Bar.class);

        try {
        for(Map.Entry<String, Class> entry : myMap.entrySet()){
          Class<?> clazz = entry.getValue();                
          Object foobar = clazz.getConstructor(  HelloWorld.class ).newInstance( new HelloWorld() );;
          System.out.println("name: " + entry.getKey() + " goes " + clazz.getMethod("chirp").invoke(foobar));
        }
    } catch (Throwable e) {
            System.err.println(e);
        }
    }
    public abstract class Foobar {
        abstract String chirp();
    }
    public class Foo extends Foobar {
        public String chirp () { return "chirp-chirp!"; }
    }
    public class Bar extends Foobar {
        public String chirp() {return "woof-woof!"; }
    }
}

1 个答案:

答案 0 :(得分:3)

FooHelloWorld的内部类,因此必须由HelloWorld的实例创建。请改为public static class Foo ...

如果Foo需要是内部类(即不是static),则需要调用相应的构造函数,例如像这样:

Foo.class.getConstructor(  HelloWorld.class ).newInstance( new HelloWorld() );

请注意,以上是一个示例,因此您可能使用clazz.getConstructor(...)。但请注意,在这种情况下,如果Bar是一个静态的“内部”类,那么该类就没有这样的构造函数。因此,如果类不同,则必须检查哪些构造函数可用。

Class<?> clazz = myMap.get(name);也足够了。

并注意:您不需要在循环中查找,只需迭代地图的条目集。此外,由于您创建了clazz的实例,因此无需致电foobar.getClass(),但可以直接使用clazz

for(Map.Entry<String, Class> entry : myMap.entrySet()){
  Class<?> clazz = entry.getValue();                
  Object foobar = ...;
  System.out.println("name: " + entry.getKey() + " goes " + clazz.getMethod("chirp").invoke(foobar));
}