Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用反射API查找字段变量或方法-Java_Java_Xml - Fatal编程技术网

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

如何使用反射API查找字段变量或方法-Java,java,xml,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:o

我正在尝试提出一种算法,它允许我将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>
将写为:

<org.powertac.common.Rate>
    <rate>0</rate>
</org.powertac.common.Rate>
我试图实现的一个例子是:

2231:org.powertac.common.Rate::7::withValue::-0.5
然后我将使用
名称,
org.powertac.common.Rate
,使用

 Class<?> c = Class.forName(args[0]);
 printMembers(c.getMethods(), "Methods");
另外,如果
方法
对象
为例,那么可能会出现一种复杂情况,因此应该有某种递归方法来产生正确的结果。 我对
Reflection
API完全是新手,所以我想知道是否有人比我更了解如何实现这一点。 谢谢

*更新
我确实可以访问这些类,并且可以实例化它们,但是,我需要找到正确的参数,因此这是一项更复杂的任务。

您的问题不清楚:您是否有用于存储数据的类?如果您还没有表示数据的类,并且不想创建它们,那么反射将不会帮助您


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

我创建示例应用程序只是为了为下面的类创建结构

class Rate
{
private double minValue;

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

public double getValue()
{
    return minValue;
}
}
下面的类使用
Reflection
创建
Rate
,然后调用
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());

        }

    }
}
}
import java.lang.reflect.InvocationTargetException;
导入java.lang.reflect.Method;
导入java.util.array;
公开课考试
{
公共静态void main(字符串[]args)抛出ClassNotFoundException、IllegalArgumentException、,
IllegaAccessException、InvocationTargetException、InstanceionException
{
Class class1=Class.forName(“费率”);
Object obj=class1.newInstance();
对于(方法m:class1.getMethods())
{
if(m.getName().equals(“withValue”))
{
类[]parameterTypes=m.getParameterTypes();
System.out.println(Arrays.toString(m.getParameterTypes());
Object methodArgs[]=新对象[parameterTypes.length];
for(类参数类型:参数类型)
{
//这里我知道有原始和双重,但你的逻辑
//应检查每种类型
if(parameterType==Double.TYPE)
{
double value=0.5;//要传递的值
//直接使用0,因为我知道只有元素存在
methodArgs[0]=值;
}
}
//现在在这里直接创建速率以进行检查,但您可能必须
//再次强制转换为泛型对象
Rate Rate=(Rate)m.invoke(obj,methodArgs);
System.out.println(rate.getValue());
}
}
}
}

我删除了我的原始评论,因为我发现您需要将日志文件格式转换为XML。只有当您能够将对象转换为XML时,Xstream才能工作。我不明白为什么需要使用反射将日志文件转换为XML。这看起来像一个简单的转换。如果我有一个新的创建对象,那么它将很容易。。。我必须在不创建objectReflection的情况下完成这一点,因为将XML转换回Java对象似乎只需要反射。但是,如果日志文件中有这些信息,为什么需要查找类呢?我有这些类,但如何创建它们呢?如果你仔细阅读这个问题,你将能够理解它的复杂性…@philippe-好的,你有类,但是为什么你需要填充它们呢?你似乎在这里制造复杂性。正如我所提到的,这只是一个粗略的想法,我完全愿意找到一个更简单的解决方案。目前还不太清楚,但很接近:例如:
2226:org.powertac.common.TariffSpecification::6::new::1::consumpion
接受一个
Broker
对象,但它只由“1”(
Broker(String id)表示
)。您需要使用相同的想法并创建对象。代理使用
parameterType
进行反射,这将使其类调用构造函数。
<org.powertac.common.Rate>
   <withValue>-0.5</withValue>
</org.powertac.common.Rate>
class Rate
{
private double minValue;

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

public double getValue()
{
    return minValue;
}
}
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());

        }

    }
}
}