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

时间:2015-08-29 19:31:59

标签: java

我有一个很长的切换声明,我正在努力提高效率。 它解析xml提要并使用xml值填充Java对象。 可能有30个字段,因此编写一个开关盒有点乏味 对于每个领域。

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;

您可以看到,处理每个案例的唯一区别是由于我正在使用的数据类型。

我正在试图弄清楚做类似的事情(伪代码)的语法:

//get the data type of this variable, somehow or other
String inputType = Observation.getMethodInputType("set" + currentTagName); 

//switch on that data type
switch(inputType) {
    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语法非常生疏,我不确定这样做的正确方法是什么(或者如果你能做到的话), 特别是对于set {currentTagName} part和getMethodInputType()(那是一个什么东西?)。

这样做的正确方法是什么?

5 个答案:

答案 0 :(得分:3)

您的解决方案将非常难以维护。 Java几乎没有以紧凑的方式解析xml的流行方法(没有繁琐的字符串操作)。

你应该检查:

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

  • DOM半可读且半快

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

对于JAXB,您必须创建将重新创建xml结构的对象/对象,并且将自动进行转换。

答案 1 :(得分:1)

不要使用switch。创建一个界面,用于按类型将String转换为对象,使用适当类型的转换器填充Map<Class,Converter>,并使用该地图中的转换器来解析您的输入。

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

现在,您可以将String转换为适当类型的Object,如下所示:

Object a = converterForClass.get(Integer.TYPE).convert("123");

这是一个使用反射访问该字段的演示:

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

Running demo.

答案 2 :(得分:1)

您可以使用以下命令将其转换为对象并获取其类名:

((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;
 }

请查看How to determine the primitive type of a primitive variable?以获取更多信息。

答案 3 :(得分:0)

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

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

Double.toString(i)

//Makes a double into a string

将所有内容都作为字符串后,比较字符串。这种方式变量类型是相同的,它使代码更容易处理。

祝你好运!

答案 4 :(得分:0)

我已经编写了一个名为unXml的小型Java-8库,可能对您有所帮助。它在Github上开源,可在Maven Central上获得。

您可以创建ObjectParser,从XPath中挑选一个值,并将其作为属性放入JsonObject。然后它使用Jackson的json-mapping来实例化你的课程。

阅读Jacksons Json to Object mapping,了解如何最好地融入您的班级。

示例:

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

您可以为xml创建一个(可重复使用的)ObjectParserapply

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部分来解析为单个parsing.arr()对象。您的parser将为ObjectParser<Birdspotting>类型(不含List)。

输出

BirdSpotting [id=1,observation=100,longitude=150.0,observationTime="15 sec"]