如何使用 JAXBContext 将单例对象保存到 XML 文件?
How to save a Singleton Object to an XML file using JAXBContext?
我希望使用 JAXBContext 将单例对象保存到 XML 文件。有问题的对象称为 Player,它正在扩展抽象 class 实体。实体也扩展线程。由于 Player 是一个单例对象,它的构造函数是私有的,并且无法从 class 外部访问。
我怎样才能正确地做到这一点?
这是我用来保存播放器的代码片段:
public static void savePlayer() throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
OutputStream os = null;
try {
os = new FileOutputStream(StringConstants.PLAYER_SAVE_FILE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
m.marshal(Player.getInstance(), os);
}
再读一遍这段代码:
public static Player readPlayer() throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Player.class);
Unmarshaller u = context.createUnmarshaller();
File f = new File(StringConstants.PLAYER_SAVE_FILE);
return (Player) u.unmarshal(f);
}
在 classes 实体和播放器上,我使用了以下注释:
@XmlRootElement
Richt 在 classes 的开头。
这是我得到的错误输出:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.lang.Thread$UncaughtExceptionHandler is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.lang.Thread$UncaughtExceptionHandler
at public java.lang.Thread$UncaughtExceptionHandler java.lang.Thread.getUncaughtExceptionHandler()
at java.lang.Thread
at model.entities.Entity
at model.entities.Player
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at model.io.SaveWriter.savePlayer(SaveWriter.java:20)
at tests.SaveTest.main(SaveTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.lang.Thread$UncaughtExceptionHandler is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.lang.Thread$UncaughtExceptionHandler
at public java.lang.Thread$UncaughtExceptionHandler java.lang.Thread.getUncaughtExceptionHandler()
at java.lang.Thread
at model.entities.Entity
at model.entities.Player
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at model.io.SaveReader.readPlayer(SaveReader.java:18)
at tests.SaveTest.main(SaveTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
终于找到问题了。如问题中所述,class 播放器扩展了 class 实体。 class 实体扩展了公共线程 class。显然,无法为线程对象正确实例化 JAXBContext。我通过让 class 实体实现 接口 Runnable 解决了这个问题,这让我没有再出现任何错误。
我希望使用 JAXBContext 将单例对象保存到 XML 文件。有问题的对象称为 Player,它正在扩展抽象 class 实体。实体也扩展线程。由于 Player 是一个单例对象,它的构造函数是私有的,并且无法从 class 外部访问。 我怎样才能正确地做到这一点?
这是我用来保存播放器的代码片段:
public static void savePlayer() throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
OutputStream os = null;
try {
os = new FileOutputStream(StringConstants.PLAYER_SAVE_FILE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
m.marshal(Player.getInstance(), os);
}
再读一遍这段代码:
public static Player readPlayer() throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Player.class);
Unmarshaller u = context.createUnmarshaller();
File f = new File(StringConstants.PLAYER_SAVE_FILE);
return (Player) u.unmarshal(f);
}
在 classes 实体和播放器上,我使用了以下注释:
@XmlRootElement
Richt 在 classes 的开头。
这是我得到的错误输出:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.lang.Thread$UncaughtExceptionHandler is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.lang.Thread$UncaughtExceptionHandler
at public java.lang.Thread$UncaughtExceptionHandler java.lang.Thread.getUncaughtExceptionHandler()
at java.lang.Thread
at model.entities.Entity
at model.entities.Player
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at model.io.SaveWriter.savePlayer(SaveWriter.java:20)
at tests.SaveTest.main(SaveTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.lang.Thread$UncaughtExceptionHandler is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.lang.Thread$UncaughtExceptionHandler
at public java.lang.Thread$UncaughtExceptionHandler java.lang.Thread.getUncaughtExceptionHandler()
at java.lang.Thread
at model.entities.Entity
at model.entities.Player
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at model.io.SaveReader.readPlayer(SaveReader.java:18)
at tests.SaveTest.main(SaveTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
终于找到问题了。如问题中所述,class 播放器扩展了 class 实体。 class 实体扩展了公共线程 class。显然,无法为线程对象正确实例化 JAXBContext。我通过让 class 实体实现 接口 Runnable 解决了这个问题,这让我没有再出现任何错误。