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方法,特别是制作mapmap
并放置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个字符串,则为是。