将类存储在Map中,以便可以实例化它们

时间:2018-04-06 16:24:29

标签: java class oop dictionary first-class

我希望能够基于HashMap条目创建类的实例。

E.g。这就是我尝试写下我的头脑:

public class One implements Interface {
  public void sayName() {
    System.out.println("One");
  }
}

public class Two implements Interface {
  public void sayName() {
    System.out.println("Two");
  }
}

Map<String, Interface> associations = new HashMap<String, Interface>();

associations.put("first", One);
associations.put("second", Two);

Interface instance = new associations.get("first")();

instance.sayName(); // outputs "One"

但我强烈怀疑这在Java中不起作用。

我的情况:我想创建一种将String名称与类关联的方法。

用户可以使用&#34; name&#34;。

创建类的实例

我想尝试:为课程制作名称地图(我不知道如何在地图中存储课程),并从地图中获取匹配&#34; name&#34;然后实例化它。

那不会奏效。

如何将类与String名称关联,并使用&#39; name&#39;来实例化这些类。我给了它吗?

3 个答案:

答案 0 :(得分:6)

您可以使用Supplier功能界面和默认构造函数的方法引用:

Map<String, Supplier<Interface>> associations = new HashMap<>();

associations.put("first", One::new);
associations.put("second", Two::new);

要实例化新对象,请致电Supplier.get

Interface foo = associations.get("first").get();

如果你的构造函数需要参数,那么你需要使用另一个functional interface。对于单参数和双参数构造函数,您可以分别使用FunctionBiFunction。还有更多,您需要定义自己的功能界面。假设构造函数都接受一个字符串,你可以这样做:

class One implements Interface
{
    One(String foo){ }

    public void sayName() {
        System.out.println("One");
    }
}

Map<String, Function<String, Interface>> associations = new HashMap<>();
associations.put("first", One::new);

然后使用Function.apply获取实例:

Interface a = associations.get("first").apply("some string");

如果你的构造者使用不同数量的参数,那么你就不幸了。

答案 1 :(得分:3)

我强烈建议Michael's answer使用Supplier。或者,您应该能够使用以下内容:

var associations = Map.of("first", One.class, "second", Two.class);

var foo = associations.get("first").getConstructor().newInstance();

如果构造函数需要参数,只需将类传递给getConstructor,将值传递给newInstance。例如,如果Two在其构造函数中使用int

var foo = associations.get("two").getConstructor(int.class).newInstance(5);

注意:这使用Java 10。

答案 2 :(得分:0)

您是想存储类并按需创建新实例,还是存储实例并只使用它们?

public class ClassInHashMap {
    public static void main(String[] args) {
    Map<String,Class<? extends SomeInterface>> associations = new HashMap<String,Class<? extends SomeInterface>>();
        associations.put("first", One.class);
        associations.put("second", Two.class);

        try {
            Class<? extends SomeInterface> someCls = associations.get("first");
            SomeInterface instance = someCls.getDeclaredConstructor().newInstance();
            instance.sayName(); // outputs "One"
        }
        catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        catch (SecurityException e) {
            e.printStackTrace();
        }
        catch (InstantiationException e) {
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

interface SomeInterface {
    public void sayName();
}

class One implements SomeInterface {
    public void sayName() {
        System.out.println("One");
    }
}

class Two implements SomeInterface {
    public void sayName() {
        System.out.println("Two");
    }
}