java - 在运行时绑定(bind)到正确的构造函数 - Java

标签 java reflection

我今天想出了一个解决方案,涉及在运行时创建类,在解析文件后,使用 Reflection Java 中的 API。

    while ((line = textReader.readLine()) != null)
    {
        Pattern p = Pattern
            .compile("([^:]+):([^:]+)::([\\d]+)::([^:]+)::(.+)");
        Matcher m = p.matcher(line);
        if (m.find())
        {
            String id = m.group(1);
            String className = m.group(2);
            int orderOfExecution = Integer.valueOf(m.group(3));
            String methodNameOrNew = m.group(4);
            Object[] arguments = m.group(5).split("::");
            if (methodNameOrNew.compareTo("new") == 0)
            {
                System.out.println("Loading class: " + className);
                if (className.contains("Competition"))
                {
                    continue;
                }
                else if (className.contains("$"))
                {
                    continue;
                }
                else
                {
                    Class<?> cl = Class.forName(className);
                    printMembers(cl.getConstructors(), "Constructor");
                    Constructor<?>[] cons = cl.getConstructors();
                    Object obj = cons[0].newInstance(arguments);
                    this.map.put(id, obj);
                }
            }
        }
    }

printMembers():

private static void printMembers(Member[] mbrs, String s)
{
    out.format("%s:%n", s);
    for (Member mbr : mbrs)
    {
        if (mbr instanceof Field)
            out.format("  %s%n", ((Field) mbr).toGenericString());
        else if (mbr instanceof Constructor)
            out.format("  %s%n", ((Constructor) mbr).toGenericString());
        else if (mbr instanceof Method)
            out.format("  %s%n", ((Method) mbr).toGenericString());
    }
    if (mbrs.length == 0)
        out.format("  -- No %s --%n", s);
    out.format("%n");
}

但是,我收到以下错误:

Loading class: org.powertac.common.TariffSpecification
Constructor:
  public org.powertac.common.TariffSpecification(org.powertac.common.Broker,org.powertac.common.enumerations.PowerType)

java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at Parser.parse(Parser.java:64)
    at Parser.main(Parser.java:137)

arguments[] 是:1 : CONSUMPTION。我怎样才能创建正确的构造函数,并给它正确的参数(类型)? 例如,在我使用的示例解析器中:

2233:org.powertac.common.Tariff::6::new::6

然后我必须创建一个类型为 org.powertac.common.Tariffclass(new 告诉我需要一个新对象被创建,它需要一个 double rate 作为参数,在本例中是 6。但是,我不知道它需要一个 double,只有参数是 String (6)。我如何创建/转换/转换为正确的类型,然后将其分配给构造函数?我的第一个想法是创建一个符号表,但我想知道更简单的解决方案...

最佳答案

您需要使用 Class.getConstructor(Class...)选择适合您希望传递给 Constructor.newInstance(Object...)

的参数的构造函数

在您的示例中,我将假设一个 1 的数组:CONSUMPTION 意味着您有一个等效于

的数组
Object[] arguments = new Object[]{Integer.valueOf(1), "CONSUMPTION"};

所以你调用下面的

Class clazz = ... //Whatever class reference you have
Constructor c = clazz.getConstructor(Integer.class, String.class);
Object obj = c.newInstance(arguments);

如果您不知道参数的类型,则必须针对 Class 返回的每个构造函数针对 Constructor.getParameterTypes() 返回的 Class 数组测试参数集。 getConstructors() 直到找到与参数数组匹配的构造函数。更具体地说,参数数组和类数组的长度相同,类数组中的每个类通过 Class.isAssignableFrom(Class) 为参数数组中相同位置的值的类.

上面的代码实现

    public boolean canConstruct(Object[] args, Constructor<?> c){
        Class<?>[] paramTypes = c.getParameterTypes(); 
        if(args.length != paramTypes.length){
            return false;
        }

        int i = 0;
        for(Object arg: args){
            if(!paramTypes[i].isAssignableFrom(arg.getClass())){
                return false;
            }
                    i++;
        }

        return true;
    }

为了使用它,你必须有你的参数数组,因为你想将它传递给构造函数。您可以尝试编辑您的输入,使其包含类型信息(这类似于 java 序列化的工作方式),以便您可以通过反射使用它们自己的类型构造函数来构造构造函数参数数组的参数

关于java - 在运行时绑定(bind)到正确的构造函数 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12151874/

相关文章:

Java:instanceof vs 类名切换性能

java - 连接和读取图像字节和字符串字节

java - 从 HashMap<Integer, List<Integer>> 获取每个数字的最大出现次数

c# - 按名称获取实体

c# - 如何使用反射对 Dispose() 进行单元测试?

java - 从 JAR 文件中的类获取值

java - 位计数方法

java - 如何提供匹配$$的正则表达式

java - 什么是NullPointerException,我该如何解决?

java - 使用runtime.exec()调用java方法