我正在开发一个概念验证对象(de)序列化框架,理想情况下能够序列化任何Object并收集有关类本身的信息。我开始使用Reflection实现它:
序列化是'简单'部分,可以实现将此规则递归地应用于对象,直到找到null或基本类型。现在,这就是我被困住的地方:反序列化。
从一个简单的对象开始,“Hello World”字符串,我有这个序列化:
<object type="java.lang.String">
<primitive name="count" type="int" value="11 />
<primitive name="hash" type="int" value="0" />
<primitive name="offset" type="int" value="0" />
<array name="value" basetype="char">
<value>H</value>
<value>e</value>
<value>l</value>
...
<value>r</value>
<value>l</value>
<value>d</value>
</array>
</object>
反序列化是可以的,因为String类有一个默认构造函数,我可以通过Reflection调用它,我可以设置所有字段。现在,让我们假设我有一个对象的以下序列化:
<object class="some-class-with-no-default-constructor">
<object name="some-attrib-name" class="attrib-1-class">
<primitive name="size" type="int" value="5" />
...
</object>
如果我没有默认构造函数会发生什么?接收参数的所有其他构造函数都不能接受'null'值作为输入,引发某种异常,因此我无法通过反射实例化该类?
问题是:“有没有办法实例化某个类的'空对象',以便在实例化后手动设置其字段而不调用其构造函数?”。当然,我也愿意讨论其他策略。
谢谢。
编辑
一旦它是一个概念验证环境,因此我没有考虑安全限制,我找到了一种方法来实例化任何对象而不通过Unsafe类调用它的构造函数。
public final class A {
private final Object o;
private A(final Object o) { if (o == null) throw new Error(); this.o = o; }
public static A a() { return new A(new Object()); }
public Object getO() { return o; }
}
上面显示的这个类是在下面的一个答案中提出的,它可以被实例化并且它的最终值设置正确(当然,前提是安全限制不适用),使用以下代码:
private static Unsafe getUnsafe() throws Exception {
Field vDeclaredField = Unsafe.class.getDeclaredFields()[0];
vDeclaredField.setAccessible(true);
Unsafe vUnsafe = (Unsafe) vDeclaredField.get(null);
vDeclaredField.setAccessible(false);
return vUnsafe;
}
public static void main(String[] args) throws Exception {
A objectA = (A) getUnsafe().allocateInstance(A.class);
Field fieldO = A.class.getDeclaredField("o");
boolean oldAccessibilityValue = fieldO.isAccessible();
fieldO.setAccessible(true);
Object objectOParameter = Arrays.asList(1,2,3,4); //could be any object
fieldO.set(objectA, objectOParameter);
fieldO.setAccessible(oldAccessibilityValue); //I personally prefer setting it to old value
assert(objectOParameter.equals(objectA.getO()));
}
所以?你们能看到与SecurityManager本身无关的任何其他问题吗?
答案 0 :(得分:4)
答案 1 :(得分:0)
有没有办法实例化 要设置的某个类的“空对象” 他们的字段后手动 实例化而不调用它 构造
不,没有。这就是为什么基于反射的框架或库通常要求它们使用的类遵循JavaBeans规范,这需要一个默认的构造函数。
克服这种情况的一种方法是要求某些类型的元数据(注释,xml)用于没有默认构造函数的类,它会告诉您使用什么值调用哪个构造函数。
答案 2 :(得分:0)
使用反射,没有可靠的方法,尽管你可以根据声明的构造函数的参数类型进行有根据的猜测。
您可以查看Objenesis。