Hãy nói rằng lớp Paradox
là trong một gói test
, như thế này (tất nhiên nó có thể là trong gói mặc định, nhưng câu hỏi không thực sự xác định nó):
package test;
public final class Paradox {
private final Paradox paradox;
public Paradox(Paradox paradox) {
this.paradox = paradox;
if (this.paradox == null) throw new InceptionException();
}
private static class InceptionException extends RuntimeException {
public InceptionException() {
super("Paradox requires an instance of paradox to be instantiated");
}
}
}
một đại diện XML, nếu nó đã được xuất bản bởi XStream, của lớp sẽ trông như thế này:
<test.Paradox/>
với XML này, nó có thể được deserialized với ra gọi constructor:
public static void main(String[] args) {
XStream xstream = new XStream(new DomDriver());
Paradox paradoxFromXml = (Paradox) xstream.fromXML("<test.Paradox/>");
System.out.println(paradoxFromXml);
}
Đầu ra là:
[email protected]
câu trả lời này có lợi thế của một thực tế rằng xStream không gọi một constructor trong deserialization , như đã nêu trong số FAQ:
XStream không gọi hàm tạo mặc định trong quá trình deserialization.
Đây là, trên thực tế, cùng trường hợp như trên. XStream sử dụng cùng một cơ chế như serialization JDK. Khi sử dụng chế độ nâng cao với API phản chiếu được tối ưu hóa, nó không gọi hàm khởi tạo mặc định. Giải pháp là để thực hiện readResolve hoặc readObject như được minh họa với câu hỏi cuối cùng.
Vì vậy, bằng cách sử dụng biểu diễn XML đơn giản XStream có theo mặc định, lớp có thể được khởi tạo thông qua quá trình deserialization, mặc dù thực tế là lớp không thể tuần tự hóa được.
Là một giải thích thêm vào đó, XStream trong trường hợp này có thể khởi tạo các lớp bằng cách sử dụng SunLimitedUnsafeReflectionProvider
hoặc SunUnsafeReflectionProvider
, mà trong nội bộ sử dụng sun.misc.Unsafe
, như bang Javadoc của họ (nhờ marco13 cho trỏ này ra):
SunLimitedUnsafeReflectionProvider
:
/**
* Instantiates a new object bypassing the constructor using undocumented internal JDK features.
* <p>
* The code in the constructor will never be executed and parameters do not have to be known. This is the same method
* used by the internals of standard Java serialization, but relies on internal code (sun.misc.Unsafe) that may not be
* present on all JVMs.
* <p>
* <p>
* The implementation will use standard Java functionality to write any fields. This requires Java 5 as minimum runtime
* and is used as fallback on platforms that do not provide the complete implementation level for the internals (like
* Dalvik).
* <p>
*
* @author Jörg Schaible
* @author Joe Walnes
* @author Brian Slesinsky
* @since 1.4.7
*/
SunUnsafeReflectionProvider
:
/**
* Instantiates a new object bypassing the constructor using undocumented internal JDK features.
* <p>
* The code in the constructor will never be executed and parameters do not have to be known. This is the same method
* used by the internals of standard Java serialization, but relies on internal code (sun.misc.Unsafe) that may not be
* present on all JVMs.
* <p>
* <p>
* The implementation will use the same internals to write into fields. This is a lot faster and was additionally the
* only possibility to set final fields prior to Java 5.
* <p>
*
* @author Joe Walnes
* @author Brian Slesinsky
* @author Jörg Schaible
* @since 1.4.7
*/
Nói chung, tôi nhớ rằng XStream có khả năng khởi tạo đối tượng mà không cần gọi hàm tạo, mà không có thời gian trả lời câu hỏi để tìm hiểu kỹ hơn.
Không thể sử dụng sự phản chiếu hoặc' sun.misc.Unsafe'. – aioobe
Ngay cả với sự phản ánh Tôi không chắc chắn bạn có thể làm điều đó – Dici
là chế nhạo một giải pháp? https://objectpartners.com/2012/03/15/how-to-mock-final-classes-in-unit-tests/ – duffy356