Java 将类存储在映射中,以便可以实例化它们

Java 将类存储在映射中,以便可以实例化它们,java,class,oop,dictionary,first-class,Java,Class,Oop,Dictionary,First Class,我希望能够基于HashMap条目创建类的实例 这就是我试图从头顶上写下的: 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&

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

这就是我试图从头顶上写下的:

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"
公共类1实现接口{ 公共名称(){ 系统输出打印项次(“一”); } } 公共类2实现接口{ 公共名称(){ System.out.println(“两个”); } } 映射关联=新的HashMap(); 协会。付诸表决(“第一”,一); 协会。付诸表决(“第二”,二); 接口实例=newassociations.get(“first”)(); instance.sayName();//产出“一” 但我强烈怀疑这在Java中不起作用


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

用户可以使用类的“名称”创建类的实例

我想尝试一下:将名称映射到类(我不知道如何在映射中存储类),从映射中获取与“name”匹配的项,然后实例化它

那不行


如何将类与
String
名称关联,并使用我给定的“名称”实例化这些类?

您可以使用函数接口和对默认构造函数的方法引用:

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

associations.put("first", One::new);
associations.put("second", Two::new);
var foo = associations.get("two").getConstructor(int.class).newInstance(5);

如果构造函数需要参数,则需要使用另一个。对于单参数和双参数构造函数,可以分别使用和。更多的时候,您需要定义自己的功能接口。假设构造函数都使用字符串,则可以执行以下操作:

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);

如果您的构造函数使用不同数量的参数,那么您就不走运了。

我强烈建议在中使用
供应商。或者,您应该能够使用以下功能:

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

var foo = associations.get("first").getConstructor().newInstance();
如果构造函数需要参数,只需将类传递给
getConstructor
,将值传递给
newInstance
。例如,如果
Two
在其构造函数中采用
int

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

associations.put("first", One::new);
associations.put("second", Two::new);
var foo = associations.get("two").getConstructor(int.class).newInstance(5);

注意:这使用Java 10。

您是要存储类并按需创建新实例,还是存储实例并仅使用它们

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");
    }
}
公共类ClassInHashMap{
公共静态void main(字符串[]args){

map您将需要查看Java反射API。这里有一个class.forName方法,特别是制作map
map
并放置
One::new
Two::new
而不是
One
Two
。然后您可以执行
关联。get(“first”).get()
。此外,您实际上不想存储类,而是要存储构造函数。从某种角度来看,构造函数只是一个函数,即调用时生成某些内容的函数。正如@Kon所说,这肯定会涉及一些反射。您可能还想查看和/或。您的映射键入错误。它应该是Class.forName方法。或者map从map中获取参数后,如何将参数传递给构造函数?我确实看到了,为什么要使用
var
关键字?最后一个
foo
类型是
Two
?我以前没有见过这个
map的
符号,如何一次向它添加单个元素?(当它被创建时,我不知道其中会包含多少元素)是的,我使用
var
只是为了缩短代码(因为它是Java10中的一个新特性).我不喜欢在Java 9中引入
Map
Map.\of
元素。要逐个添加元素,只需初始化
HashMap
放入
条目。我需要创建一个接受“构造函数”的函数(
one::new
Two::new
),什么是
类::new
的类型签名?它没有类型。它将匹配任何具有相同数量参数并返回
接口的函数接口。我需要创建一个包装
关联的函数。put
,此函数采用
字符串
键和
类::new
值。函数将看起来像
void addAssoc(字符串名称,XXX构造函数)
。是否
XXX
将成为
函数
?如果构造函数都使用1个字符串,则为是。