由NullPointerException引起的UnmarshalException

时间:2017-07-01 17:48:31

标签: exception javafx nullpointerexception

我正在处理一个应用程序,我需要将ObservableArrayList中的数据保存并加载到XML文件中。我为ObservableList创建了一个带有Double和Integer属性的模型类:

   package application.Model;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;    
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;

@XmlRootElement
@XmlType(name = "Object", propOrder = {"diameter", "handeling", "aantal", "basisUren", "correctie", "toeslagUren", "totaalUren", "totaalMat", "totaal"})
public class Berekening {
    private final SimpleIntegerProperty diameter;
    private final SimpleIntegerProperty handeling;
    private final SimpleIntegerProperty aantal;
    private final SimpleDoubleProperty basisUren;
    private final SimpleDoubleProperty correctie;
    private final SimpleDoubleProperty toeslagUren;
    private final SimpleDoubleProperty totaalUren;
    private final SimpleDoubleProperty totaalMat;
    private final SimpleDoubleProperty totaal;


    public Berekening() {
        this(null, null, null, null, null, null, null, null, null);
    }

    public Berekening(Integer diameter, Integer handeling, Integer aantal, Double basisUren, Double correctie, Double toeslagUren, Double totaalUren, Double totaalMat, Double totaal) {
        this.diameter = new SimpleIntegerProperty(diameter);
        this.handeling = new SimpleIntegerProperty(handeling);
        this.aantal = new SimpleIntegerProperty(aantal);
        this.basisUren = new SimpleDoubleProperty(basisUren);
        this.correctie = new SimpleDoubleProperty(correctie);
        this.toeslagUren = new SimpleDoubleProperty(toeslagUren);
        this.totaalUren = new SimpleDoubleProperty(totaalUren);
        this.totaalMat = new SimpleDoubleProperty(totaalMat);
        this.totaal = new SimpleDoubleProperty(totaal);
    }

    @XmlElement (name = "value1", required = false)
        public Integer getDiameter() {
        return diameter.get();
    }

    public void setDiameter(int diameter) {
        this.diameter.set(diameter);
    }

    public IntegerProperty diameterProperty(){
        return diameter;
    }

    @XmlElement (name = "value2", required = false)
    public Integer getHandeling() {
        return handeling.get();
    }

    public void setHandeling(int handeling) {
        this.handeling.set(handeling);
    }

    public IntegerProperty handelingProperty(){
        return handeling;
    }

    @XmlElement (name = "value3", required = false)
    public Integer getAantal() {
        return aantal.get();
    }

    public void setAantal(int aantal) {
        this.aantal.set(aantal);
    }

    public IntegerProperty aantalProperty(){
        return aantal;
    }

    @XmlElement (name = "value4", required = false)
    public Double getBasisUren(){
        return basisUren.get();
    }

    public void setBasisUren(double value) {
        this.basisUren.set(value);
    }

    public DoubleProperty basisUrenProperty(){
        return basisUren;
    }

    @XmlElement (name = "value5", required = false)
    public Double getCorrectie(){
        return correctie.get();
    }

    public void setCorrectie(double value) {
        this.correctie.set(value);
    }

    public DoubleProperty correctieProperty(){
        return correctie;
    }

    @XmlElement (name = "value6", required = false)
    public Double getToeslagUren(){
        return toeslagUren.get();
    }

    public void setToeslagUren(double value) {
        this.toeslagUren.set(value);
    }

    public DoubleProperty toeslagUrenProperty(){
        return toeslagUren;
    }

    @XmlElement (name = "value7", required = false)
    public Double getTotaalUren(){
        return totaalUren.get();
    }

    public void setTotaalUren(double value) {
        this.totaalUren.set(value);
    }

    public DoubleProperty totaalUrenProperty(){
        return totaalUren;
    }

    @XmlElement (name = "value8", required = false)
    public Double getTotaalMat(){
        return totaalMat.get();
    }   

    public void setTotaalMat(double value) {
        this.totaalMat.set(value);
    }

    public DoubleProperty totaalMatProperty(){
        return totaalMat;
    }
    @XmlElement (name = "value9", required = false)
    public Double getTotaal(){
        return totaal.get();
    }

    public void setTotaal(double value) {
        this.totaal.set(value);
    }

    public DoubleProperty totaalProperty(){
        return totaal;
    }
    }

这是列表类:

    package application.Model;

    import java.util.ArrayList;
    import java.util.List;

    import javax.xml.bind.annotation.XmlElement;

    public class BerekeningList {
@XmlElement(name = "berekening")

List<Berekening> berekeningen = new ArrayList<>();

public List<Berekening> getBerekeningen() {
    return berekeningen;
}
    }

ListWrapper:

    package application.Model;

    import java.util.List;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlElements;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

    import application.MainApp;
    import application.Util.BerekeningListAdapter;
    import javafx.collections.ObservableList;

@XmlRootElement (name = "Berekeningen")
public class BerekeningListWrapper{

    private ObservableList<Berekening> berekening;

    @XmlJavaTypeAdapter(BerekeningListAdapter.class)
        public ObservableList<Berekening> getBerekeningen(){
            return berekening;
        }

    public void setBerekenings(ObservableList<Berekening> berekenings) {
        this.berekening = berekenings;
    }

}

我使用此方法将数据保存到文件中:

        public void saveBerekeningDataToFile(File file) {
    try {
        JAXBContext context = JAXBContext
                .newInstance(BerekeningListWrapper.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        BerekeningListWrapper wrapper = new BerekeningListWrapper();
        wrapper.setBerekenings(berekeningData);

        m.marshal(wrapper, file);

        setBerekeningFilePath(file);
    } catch (Exception e) {
        Alert alert = new Alert(AlertType.ERROR);
        alert.setTitle("Error");
        alert.setHeaderText("Could not save data");
        alert.setContentText("Could not save data to file:\n" + file.getPath());

        alert.showAndWait();
    }
}

生成的xml文件(保存似乎工作正常):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Berekeningen>
<berekeningen>
    <berekening value1="15" value2="5" value3="5" value4="1.25" value5="5.0" value6="6.25" value7="270.0" value8="30.0" value9="300.0"/>
</berekeningen>

问题是将数据加载回我的应用程序,我正在使用这种方法:

    public void loadBerekeningDataFromFile(File file){
    try {
        JAXBContext context = JAXBContext
                .newInstance(BerekeningListWrapper.class);
        Unmarshaller um = context.createUnmarshaller();

        BerekeningListWrapper wrapper = (BerekeningListWrapper)um.unmarshal(file);

        berekeningData.clear();
        berekeningData.addAll(wrapper.getBerekeningen());

        setBerekeningFilePath(file);

    } catch (Exception e){
        e.printStackTrace();
        Alert alert = new Alert(AlertType.ERROR);
        alert.setTitle("Error");
        alert.setHeaderText("Could not load data");
        alert.setContentText("Could not load data from file:\n" + file.getPath());

        alert.showAndWait();
        }
    }

导致以:

开头的堆栈跟踪
    javax.xml.bind.UnmarshalException: Unable to create an instance of 
    application.Model.Berekening
    etc 
    Caused by: java.lang.NullPointerException
    at application.Model.Berekening.<init>(Berekening.java:32)
    at application.Model.Berekening.<init>(Berekening.java:28)
    ... 84 more

因此,unmarshalexception是由模型类中的NullPointerException引起的:

    this.diameter = new SimpleIntegerProperty(diameter);

    and

    this(null, null, null, null, null, null, null, null, null);

我不知道如何解决这个问题,我已经在StackOverflow上尝试了很多不同的教程和答案,但我没有发现任何问题。 非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

您无法使用SimpleIntegerProperty初始化nullconstructor you are calling需要int,因此当您致电diameter.intValue()时,new SimpleIntegerProperty(diameter)会隐式调用(&#34;取消装箱&#34;)。显然,如果diameternull,则会产生NullPointerException

使数值类型的默认值为非null:

public Berekening() {
    this(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
} 
例如,

如果你真的需要支持空值(这是一个不太优选的选项,imho),请使用ObjectProperty代替IntegerPropertyDoubleProperty

public class Berekening {
    private final ObjectProperty<Integer> diameter;
    private final ObjectProperty<Integer> handeling;
    private final ObjectProperty<Integer> aantal;
    private final ObjectProperty<Double> basisUren;
    private final ObjectProperty<Double> correctie;
    private final ObjectProperty<Double> toeslagUren;
    private final ObjectProperty<Double> totaalUren;
    private final ObjectProperty<Double> totaalMat;
    private final ObjectProperty<Double> totaal;


    public Berekening() {
        this(null, null, null, null, null, null, null, null, null);
    }

    public Berekening(Integer diameter, Integer handeling, Integer aantal, Double basisUren, Double correctie, Double toeslagUren, Double totaalUren, Double totaalMat, Double totaal) {
        this.diameter = new SimpleObjectProperty<>(diameter);
        this.handeling = new SimpleObjectProperty<>(handeling);
        this.aantal = new SimpleObjectProperty<>(aantal);
        this.basisUren = new SimpleObjectProperty<>(basisUren);
        this.correctie = new SimpleObjectProperty<>(correctie);
        this.toeslagUren = new SimpleObjectProperty<>(toeslagUren);
        this.totaalUren = new SimpleObjectProperty<>(totaalUren);
        this.totaalMat = new SimpleObjectProperty<>(totaalMat);
        this.totaal = new SimpleObjectProperty<>(totaal);
    }

    // ...
}