JAXB unmarshalling返回Null [英] JAXB unmarshalling returning Null
问题描述
我正在制作这个示例GUI,它只是将计算机部件从一侧移动到另一侧,并能够将列表(以xml格式)加载并保存到桌面。除了重新加载已保存的xml文件外,一切正常。我认为它与Save.java中的注释有关。话虽如此,我不确定需要什么或者问题是什么。任何帮助将不胜感激。
I'm making this example GUI that simply moves computer parts from one side to another, with the ability to load and save list (in xml) to the desktop. Everything works fine except for the reloading of saved xml files. I think it has something to do with the annotations in the Save.java. That being said I'm not sure what is needed or if that is the issue. Any help will be appreciated.
Window.java
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.DefaultListModel;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.ListSelectionModel;
import java.awt.Component;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.BoxLayout;
import javax.swing.JList;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
public class Window {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Window window = new Window();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Window() {
initialize();
}
public void addTo(JPanel displayPanel, Component contentToAdd)
{
displayPanel.add(contentToAdd);
}
public void initialize() {
//setting the dimension for the JList panels
Dimension sidePanelSize = new Dimension(180, 540);
frame = new JFrame();
frame.setBounds(100, 100, 480, 540);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Creating the menu bar
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
//adding File option to menu bar
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
//adding load option to File
JMenuItem mntmLoad = new JMenuItem("Load");
mnFile.add(mntmLoad);
//adding save option to File
JMenuItem mntmSave = new JMenuItem("Save");
mnFile.add(mntmSave);
//adding exit option to File
JMenuItem mntmExit = new JMenuItem("Exit");
mnFile.add(mntmExit);
//creating Jpanel that will hold JList for computer parts
//that you can choose
final JPanel itemPanel = new JPanel();
itemPanel.setPreferredSize(sidePanelSize);
itemPanel.setBackground(Color.WHITE);
itemPanel.setLayout(new BorderLayout());
//Create the model that will hold the computer items
//For loop to add the strings to the model
DefaultListModel<String> model = new DefaultListModel<>();
for (String items : new String [] {"Case", "Motherboard", "CPU", "GPU", "PSU", "RAM", "HDD"})
model.addElement(items);
//Create JList(itemList) and set its model to the one
//holding the computer parts
final JList<String> itemList = new JList<>(model);
//Setting attributes for the JList(itemList) - font, Number of elements you can select at a time
itemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
itemList.setFont(new Font("SegoeUI", Font.BOLD, 11));
//adding the JList to the Panel
itemPanel.add(itemList, BorderLayout.WEST);
//adding the Panel to the frame
frame.getContentPane().add(itemPanel, BorderLayout.WEST);
//creating two panels that are used for centering the JList buttons
JPanel buttonContainer = new JPanel();
JPanel buttonList = new JPanel();
GridBagConstraints c = new GridBagConstraints();
//setting the layout managers for the panels and
//adding color to the background
buttonList.setLayout(new BoxLayout(buttonList, BoxLayout.Y_AXIS));
buttonContainer.setLayout(new GridBagLayout());
buttonContainer.setBackground(new Color(238, 238, 238));
//adding the button to add content from Jlist on the left(itemList)
//to the right JList(addToList)
JButton addButton = new JButton(">>");
buttonList.add(addButton);
//adding the button to remove content form the JList(addToList)
JButton deleteButton = new JButton("<<");
buttonList.add(deleteButton);
//setting where to start inputing element into the
//grid of the ButtonContainer
c.gridx = 0;
c.gridy = 0;
//adding the button panel container and its constraints
//to the main container
//finally adding it all to the main frame
buttonContainer.add(buttonList, c);
frame.getContentPane().add(buttonContainer, BorderLayout.CENTER);
//creating the JList that we will add and remove from
final JList<String> addToList = new JList<>(new DefaultListModel<String>());
//creating the panel to hold the JList(addToList)
//setting its size and layout in the manager
//finally adding it to the main frame
final JPanel displayPanel = new JPanel();
displayPanel.setPreferredSize(sidePanelSize);
displayPanel.setBackground(Color.WHITE);
displayPanel.add(addToList, BorderLayout.EAST);
frame.getContentPane().add(displayPanel, BorderLayout.EAST);
//Here is all the action listeners for button click events and menu events
//contains all the methods for the action events
final ActionListeners b = new ActionListeners();
//Listener that adds selected computer parts from left JList(itemList) to the right JList(addToList)
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
b.addContent(itemList, addToList);
}
});
//Listener that removes selected computer part from the JList(addToList)
deleteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
b.removeContent(addToList);
}
});
//Listener that calls the save methods to save JList(addToList) content into xml
mntmSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
b.saveContent((DefaultListModel<String>) addToList.getModel());
}
});
//Listener that call the load methods to load xml into the JList(addToList)
mntmLoad.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
b.loadContent(addToList);
}
});
//Exits the program entirely
mntmExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
b.exitProgram();
}
});
}
}
Load.java
import java.io.File;
import javax.swing.DefaultListModel;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class Load {
//loads the file into the JList to be displayed in the program
public DefaultListModel<String> loadXMLFile() {
//array that holds the content from the xml file
//model that will have xml file's content added to it
//from the array
DefaultListModel<String> modelToReturn = new DefaultListModel<>();
String[] partsList = null;
try {
String homeDir = System.getProperty("user.home");
File file = new File(homeDir + "/Desktop/xml.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Save.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Save load = (Save) jaxbUnmarshaller.unmarshal(file);
partsList = new String [load.getPartsList().length];
} catch (JAXBException e) {
e.printStackTrace();
}
//adds the strings in the arrayToReturn
//to the model that will be returned
for(int i = 0; i < partsList.length; i++)
{
modelToReturn.addElement(partsList[i]);
}
return modelToReturn;
}
}
ActionListeners.java
import java.io.File;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class ActionListeners {
public void addContent(JList<String> itemList, JList<String> addToList)
{
//gets the value selected to be added to other other JList
List<String> selected = itemList.getSelectedValuesList();
//gets the model of the List to be added too
DefaultListModel<String> displayModel = (DefaultListModel<String>) addToList.getModel();
//adds the elements to the JList
for (String item: selected)
{
displayModel.addElement(item);
}
}
public void removeContent(JList<String> addToList)
{
//gets the element selected to be removed
List<String> selected = addToList.getSelectedValuesList();
//gets the model of the JList where content will be removed
DefaultListModel<String> displayModel = (DefaultListModel<String>) addToList.getModel();
//removes the selected element
for (String item: selected) {
displayModel.removeElement(item);
}
}
public void saveContent(DefaultListModel<String> addToList)
{
Save saveFile = new Save();
//adds the content in the JList to be saved
//to the object
saveFile.setPartsList(addToList);
try {
JAXBContext jaxbContext =
JAXBContext.newInstance(Save.class);
Marshaller jaxbMarshaller =
jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
String homeDir = System.getProperty("user.home");
jaxbMarshaller.marshal(saveFile, new File(homeDir + "/Desktop", "xml.xml"));
jaxbMarshaller.marshal(saveFile, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
//saves the content
//saveFile.saveFileXml();
}
public void loadContent(JList<String> addToList)
{
Load loadFile = new Load();
//gets the model of the JList that loaded content will be added too
DefaultListModel<String> newModel= (DefaultListModel<String>) addToList.getModel();
//makes sure the model is clear
newModel.removeAllElements();
//makes model that the loaded content will be set too
DefaultListModel<String> loadedModel = loadFile.loadXMLFile();
//adds the loaded elements from the file to JList's model
for(int i = 0; i < loadedModel.getSize(); i++)
{
newModel.addElement(loadedModel.get(i));
}
}
public void exitProgram()
{
//closes the entire program
System.exit(0);
}
}
Save.java
import javax.swing.DefaultListModel;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement (name = "lists")
public class Save {
//array that will hold the content to be saved
String[] partsListSave;
//method to set the array partsListSave
//with the content that will be saved
public void setPartsList(DefaultListModel<String> model) {
//Initialize the array with the length of the content
//to be added
partsListSave = new String[model.getSize()];
//adds the content to the array
for (int i = 0; i < model.getSize(); i++)
{
partsListSave[i] = model.getElementAt(i);
}
}
@XmlElement (name = "parts")
public String[] getPartsList() {
return partsListSave;
}
}
xml.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<lists>
<parts>Motherboard</parts>
<parts>Motherboard</parts>
<parts>Motherboard</parts>
<parts>Motherboard</parts>
</lists>
推荐答案
您的 Save.java
class需要一个合适的setter方法:
Your Save.java
class needs an appropriate setter method:
public void setPartsList(String[] partsListSave) {
this.partsListSave = partsListSave;
}
为验证这一点,我创建了文件 xml.xml
:
To verify this, I created file xml.xml
:
<lists>
<parts>Part 1</parts>
<parts>Part 2</parts>
<parts>Part 3</parts>
</lists>
测试类包含:
public static void main(String[] args) throws Exception {
File file = new File("xml.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Save.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Save load = (Save) jaxbUnmarshaller.unmarshal(file);
for (String parts : load.getPartsList())
System.out.println(parts);
}
使用 Save.java
,NPE失败了。添加setter工作。
With your Save.java
, it failed with NPE. Adding the setter worked.
最小,完整且可验证。
注意
您的问题部分基于误解。
Your question is partly based on a misunderstanding.
JAXB unmarshaller(对 jaxbUnmarshaller.unmarshal(文件);
的调用)不返回 null
- 它会返回保存
的实例。
unmarshal()
本身永远不会返回 null
(参见 Unmarshaller
的API文档: unmarshal方法永远不会返回null。) - 但它返回的实例中的字段可能是 null
。
The JAXB unmarshaller (the call to jaxbUnmarshaller.unmarshal(file);
) does not return null
- it returns an instance of Save
, as it should.
unmarshal()
itself never returns null
(see API docs of Unmarshaller
: "An unmarshal method never returns null.") - however the fields in the instance it returns may be null
.
在这种情况下,字段 Save.partsListSave
是 null
,因为JAXB无法设置它,因为没有合适的setter,如上所述。
In this case the field Save.partsListSave
is null
, because JAXB cannot set it, since there is no appropriate setter, as explained above.
您看到的NullPointerException是由尝试使用 getPartsList()
返回的值引起的,这是 null
。
The NullPointerException you see is caused by trying to use the value returned by getPartsList()
, which is null
.
这篇关于JAXB unmarshalling返回Null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!