Java 如何打开对象字段的数据类型?

Java 如何打开对象字段的数据类型?,java,Java,我有一个很长的switch语句,我正在努力提高效率。 它解析xml提要并使用xml值填充Java对象。 可能有30个字段,所以写一个switch case有点乏味 对于每个字段 switch (currentTagName) { case "longitude" : observation.setLongitude(Double.parseDouble(parser.getText())); break; case "elevation" :

我有一个很长的switch语句,我正在努力提高效率。 它解析xml提要并使用xml值填充Java对象。 可能有30个字段,所以写一个switch case有点乏味 对于每个字段

switch (currentTagName) {
    case "longitude" :
        observation.setLongitude(Double.parseDouble(parser.getText()));
        break;
    case "elevation" :
        observation.setElevation(Integer.parseInt(parser.getText()));
        break;
    case "observation_time" :
        observation.setObservation_time(parser.getText());
        break;
您可以看到,每个案例处理方式的唯一区别在于我使用的数据类型

我试图找出执行类似操作的语法(伪代码):

只是我的Java语法太生疏了,我不确定正确的方法是什么(或者如果你能做到的话), 特别是对于集合{currentTagName}部分和getMethodInputType()(这是一件事吗?)


正确的方法是什么?

将int和double转换为字符串,然后使用一个if语句。使用以下语法:

Integer.toString(i)
//Makes an integer into a string

一旦您将所有内容都作为字符串,请比较字符串。这样,变量类型是相同的,并且使代码更容易处理


祝你好运

不要使用
开关
。创建一个接口,用于将
字符串
按类型转换为对象,使用适当类型的转换器填充
映射
,并使用该映射中的转换器解析输入

interface Converter {
    Object convert(String s);
}
private static Map<Class,Converter> converterForClass = new HashMap<>();
static {
    converterForClass.put(Integer.TYPE, s -> Integer.parseInt(s));
    converterForClass.put(Double.TYPE, s -> Double.parseDouble(s));
    converterForClass.put(String.class, s -> s);
    converterForClass.put(Long.TYPE, s -> Long.parseLong(s));
};
下面是一个使用反射访问字段的演示:

static class Demo {
    public int a;
    public long b;
    public String c;
    public double d;
    @Override
    public String toString() {
        return a+":"+b+":'"+c+"':"+d;
    }
}

public static void main (String[] args) throws java.lang.Exception
{
    Object a = new Demo();
    Map<String,String> data = new HashMap<>();
    data.put("a", "123");
    data.put("b", "123456678789898");
    data.put("c", "HELLO");
    data.put("d", "123.456");
    for (Field f : Demo.class.getDeclaredFields()) {
        f.setAccessible(true);
        String str = data.get(f.getName());
        Object r = converterForClass.get(f.getType()).convert(str);
        f.set(a, r); // Call set(target, objValue) instead of setInt, setLong, etc.
    }
    System.out.println(a);
}
静态类演示{
公共INTA;
公共长b;
公共字符串c;
公共双d;
@凌驾
公共字符串toString(){
返回a+“:“+b+”:“+c+”:“+d;
}
}
公共静态void main(字符串[]args)引发java.lang.Exception
{
对象a=新的演示();
映射数据=新的HashMap();
数据。出售(“a”、“123”);
数据。投入(“b”,“1234566789898”);
data.put(“c”、“HELLO”);
数据。投入(“d”,“123.456”);
对于(字段f:Demo.class.getDeclaredFields()){
f、 setAccessible(true);
String str=data.get(f.getName());
objectr=converterForClass.get(f.getType()).convert(str);
f、 set(a,r);//调用set(target,objValue)而不是setInt、setLong等。
}
系统输出打印项次(a);
}

您可以简单地将其转换为对象,并使用以下方法获取其类名:

((Object) yourVar).getClass().getName()
然后可以在switch语句中使用它:

String typeName =  ((Object) inputType).getClass().getName();

switch(typeName) { 

   case "Integer":      

            observation.set{currentTagName}(Integer.parseInt(parser.getText())); 
   break; 

   case "Double":

             observation.set{currentTagName}(Double.parseDouble(parser.getText())); 
    break; 

    case "String":

              observation.set{currentTagName}(parser.getText()); 
    break;
 }

查看更多信息。

您的解决方案将无法维护。Java很少有以紧凑的方式解析xml的流行方法(没有繁琐的字符串操作)

您应该检查:

  • (推荐)它提供了良好的域封装和非常可读的代码

  • 它是半可读半快速的

  • 这是非常快和最不可维护的

对于JAXB,您必须创建一个或多个对象,这些对象将重新创建xml结构,转换将自动进行。

我编写了一个名为的Java-8库,这可能对您有所帮助。它在Github上开源,在Maven Central上可用

您可以创建一个
ObjectParser
,它将从
XPath
中选择一个值,并将其作为属性放入
JsonObject
。然后它使用Jackson的json映射来实例化您的类

阅读有关Jackson的文章,看看如何让它最适合你的课程

例如:

您可以创建一个(可重用的)
ObjectParser
,并将其应用于xml

public List<BirdSpotting> getData(Document inputXml) {
    Parsing parsing = ParsingFactory.getInstance().create();

    ObjectParser<List<BirdSpotting>> parser = 
        parsing.arr("/root/entry", parsing.obj()
            .attribute("id", "@id")
            .attribute("observation", "observation", parsing.with(Integer::parseInt))
            .attribute("longitude", "longitude", parsing.with(Double::parseDouble))
            .attribute("observationTime", "observation-time")
    ).as(BirdSpotting.class);

    List<BirdSpotting> spottings = parser.apply(inputXml);
    return spottings;
}

虽然这是一个很好的解决方案,但是为不同的标记调用不同的setter方法(使用不同的名称)的问题仍然存在。也许您可以通过一些反射来改进您的解决方案,从而查找要将数据放入其中的字段。@ThomasJunk必须为不同类型调用不同方法的问题完全消失了,因为有一个
set
方法接受
对象
(请参见演示)。当然,如果一个人坚持根据类型调用不同的方法,而不是转换和返回对象,lambda可以将字段和目标作为附加参数,并在内部进行设置。哇,我忘了Java在多大程度上拥有一个用于所有内容的库。我认为JAXB是我所追求的。这个解决方案会起作用,但对于switch语句来说,这可能不是一个好的用例。@ChakladerAsfakArefe是的,我完全同意
switch
case在这里不是最好的解决方案,但我只是纠正了OP代码。
((Object) yourVar).getClass().getName()
String typeName =  ((Object) inputType).getClass().getName();

switch(typeName) { 

   case "Integer":      

            observation.set{currentTagName}(Integer.parseInt(parser.getText())); 
   break; 

   case "Double":

             observation.set{currentTagName}(Double.parseDouble(parser.getText())); 
    break; 

    case "String":

              observation.set{currentTagName}(parser.getText()); 
    break;
 }
<root>
    <entry id="1">
        <observation>100</observation>
        <longitude>150</longitude>
        <observation-time>15 sec</observation-time>
    </entry>
</root>
@JsonIgnoreProperties(ignoreUnknown = true)
public static class BirdSpotting {
    public Integer id;
    public Integer observation;
    public Double longitude;
    public String observationTime;
}
public List<BirdSpotting> getData(Document inputXml) {
    Parsing parsing = ParsingFactory.getInstance().create();

    ObjectParser<List<BirdSpotting>> parser = 
        parsing.arr("/root/entry", parsing.obj()
            .attribute("id", "@id")
            .attribute("observation", "observation", parsing.with(Integer::parseInt))
            .attribute("longitude", "longitude", parsing.with(Double::parseDouble))
            .attribute("observationTime", "observation-time")
    ).as(BirdSpotting.class);

    List<BirdSpotting> spottings = parser.apply(inputXml);
    return spottings;
}
BirdSpotting [id=1,observation=100,longitude=150.0,observationTime="15 sec"]