如何使用Reflection API查找字段变量或方法 - Java

时间:2012-08-29 13:04:47

标签: java xml

我正在尝试提出一种算法,它允许我将Java类编组为XML而不创建该类的对象(这是问题所在,而且我使用的工具非常复杂)。我必须从日志文件中读取数据并将其转换为XML文件。 日志文件中的示例:

2206:org.powertac.common.RandomSeed::4::init::TariffMarket::0::fees::-6239716112490883981
2213:org.powertac.common.msg.BrokerAccept::null::new::1
2214:org.powertac.common.msg.BrokerAccept::null::new::1::null
2216:org.powertac.common.RandomSeed::5::init::org.powertac.du.DefaultBrokerService::0::pricing::8741252857248937781
2226:org.powertac.common.TariffSpecification::6::new::1::CONSUMPTION
2231:org.powertac.common.Rate::7::new
2231:org.powertac.common.Rate::7::withValue::-0.5
2232:org.powertac.common.Rate::7::setTariffId::6

日志文件的模式是:

<id>:<class_name>::<order_of_execution>::<method_or_new>::<arguments>

因此,我想将以下一行翻译成XML

2231:org.powertac.common.Rate::7::new

将写成:

<org.powertac.common.Rate>
    <rate>0</rate>
</org.powertac.common.Rate>

我有解析器给我值,所以我可以访问这些数据。我到目前为止的想法是为我使用Reflection Java API来处理脏工作,否则我必须创建一个符号表来完成我想要的工作。我知道我可以使用Reflection API来查找符号:

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

我想要完成的一个例子是:

2231:org.powertac.common.Rate::7::withValue::-0.5

然后我会使用class名称org.powertac.common.Rate,使用Class

 Class<?> c = Class.forName(args[0]);
 printMembers(c.getMethods(), "Methods");

返回方法withValue及其参数,因此我可以通过编程方式创建以下XML代码:

<org.powertac.common.Rate>
   <withValue>-0.5</withValue>
</org.powertac.common.Rate>

此外,如果methodclassobject为例,那么可能存在一个潜在的复杂因素,因此应该采用某种递归方法来产生正确的结果。 我对Reflection API完全不满意,所以我想知道是否有人比我更了解如何实现这一目标。 感谢

*的 更新 我可以访问类,我可以实例化它们,但是,我需要找出正确的参数,所以这是一个更复杂的任务。

2 个答案:

答案 0 :(得分:1)

您的问题不明确:您是否有用于存储数据的课程,或者不是吗?如果您还没有代表数据的类,并且不想创建它们,那么反射对您没有帮助。

相反,我建议只使用JAXP来生成输出。创建一个Document,向其中添加Element子项,然后使用序列化程序生成输出。谷歌为“DOM教程”找到了一些例子。

答案 1 :(得分:0)

我创建了示例应用程序,只是为了创建后续类

的结构
class Rate
{
private double minValue;

public Rate withValue(double value)
{
    minValue = value;
    return this;
}

public double getValue()
{
    return minValue;
}
}

以下课程使用Rate创建Reflection,然后致电withValue API

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test
{

public static void main(String[] args) throws ClassNotFoundException, IllegalArgumentException,
        IllegalAccessException, InvocationTargetException, InstantiationException
{
    Class<?> class1 = Class.forName("Rate");
    Object obj = class1.newInstance();
    for (Method m : class1.getMethods())
    {
        if (m.getName().equals("withValue"))
        {
            Class<?>[] parameterTypes = m.getParameterTypes();
            System.out.println(Arrays.toString(m.getParameterTypes()));
            Object methodArgs[] = new Object[parameterTypes.length];
            for (Class<?> parameterType : parameterTypes)
            {
                // Here I know there is primitive and double but your logic
                // should check for each and every type
                if (parameterType == Double.TYPE)
                {
                    double value = 0.5;// Value to be passed
                    // directly using 0 since I know only element is there
                    methodArgs[0] = value;
                }
            }
            // Now Creating Rate here directly to check but you may have to
            // again cast to generic object
            Rate rate = (Rate) m.invoke(obj, methodArgs);
            System.out.println(rate.getValue());

        }

    }
}
}