如何使用反射API查找字段变量或方法-Java
我正在尝试提出一种算法,它允许我将Java类编组为XML,而无需创建该类的对象(这就是问题所在,使用我现有的工具非常复杂)。我必须从日志文件中读取数据并将其转换为XML文件。 日志文件中的示例:如何使用反射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
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());
}
}
}
}