Java - 导致程序无法正常工作的方法的存在

时间:2015-06-28 17:11:36

标签: java serialization

在我的Java程序中,我有一个名为Car的类,它是Serializable。我有另一个名为StaffCar的类,它是Car的子类。

然后有一个名为Fleet的类,它基本上将StaffCar个对象存储在ArrayList<StaffCar> fleet中。

然后我有一个课程Main,其中包含main方法,该方法包含菜单和switch处理菜单选项。

我遇到的问题是当我在StaffCar中添加方法时,即使该方法内部没有 且该方法甚至未被调用,菜单选项是&#39;显示所有汽车信息&#39;,停止工作。

如果我注释掉这个方法,它会再次开始工作。

&#39;显示...&#39;来自printCars()的{​​{1}}选项调用Fleet,其中fleet加载了序列化文件中的StaffCar个对象,就像这种方法的存在一样,即使是读取。

Car

的摘录
import java.util.ArrayList;
import java.io.*;

@SuppressWarnings("serial")
public class Car implements Serializable
{
    //attributes for Car
    String regNo;
    String model;
    int mileage;

    //default constructor
    public Car() throws CarException
    {
        try 
        {
            setRegNo("??????");
            setModel("Unknown");
            setMileage(0);
        }
        catch (CarException c) 
        {
            System.out.println(c.getMessage());
        }
    }

    //setters
    public void setRegNo(String regNo) throws CarException
    {
        if (regNo.isEmpty())
        {
            throw new CarException("\nInvalid registration number!\n");
        }
        this.regNo = regNo;
    }

    public void setModel(String model) throws CarException
    {
        if (model.isEmpty())
        {
            throw new CarException("\nModel can't be empty!\n");
        }
        this.model = model;
    }

    public void setMileage(int mileage) throws CarException
    {
        if (mileage < 0)
        {
            throw new CarException("\nInvalid mileage!");
        }
        this.mileage = mileage;
    }
}

StaffCar的片段,导致问题的原因

import java.util.ArrayList;

@SuppressWarnings("serial")
public class StaffCar extends Car
{
    String staffName;
    String availability;

    public StaffCar() throws CarException
    {
        super();
        try 
        {
            setAvailability("Available");
            setStaffName("");
        }
        catch (CarException c)
        {
            System.out.println(c.getMessage());
        }
    }

    public void setStaffName(String staffName)
    {
        this.staffName = staffName;
    }

    public void setAvailability(String availability) throws CarException
    {
        if (availability != "Available" && availability != "Borrowed")
        {
            throw new CarException("\nInvalid borrow status!\n");
        }
        this.availability = availability;
    }

    //this method causing issues, even if empty
    /*public void returnCar()
    {
    }*/
}

Fleet

的摘录
import java.util.ArrayList;
import java.io.*;

public class Fleet 
{
    //declare container
    ArrayList<StaffCar> fleet;
    //container to hold regNos
    ArrayList<String> regNumbers;

    //create constructor
    public Fleet()
    {
        fleet = new ArrayList<StaffCar>();
        regNumbers = new ArrayList<String>();
    }

    //add method
    public void addCar(StaffCar car)
    {
        fleet.add(car);
        regNumbers.add(car.regNo);
    }

    //print all cars' details
    public void printCars()
    {
        for (StaffCar car:fleet)
        {
            System.out.println(car);
        }
    }

    public void saveAs(String fileName) throws CarException
    {
        FileOutputStream outputFile;

        try
        {
            outputFile = new FileOutputStream(fileName);
        }
        catch (IOException io)
        {
            throw new CarException("\nCannot create " + fileName + "\n");
        }

        ObjectOutputStream fleetFile;

        try
        {
            fleetFile = new ObjectOutputStream(outputFile);
            fleetFile.writeObject(regNumbers);
            fleetFile.writeObject(fleet);
            fleetFile.close();
        }
        catch (FileNotFoundException e)
        {
            throw new CarException("\nCannot create " + fileName + "\n");
        }
        catch (IOException io)
        {
            throw new CarException("\nCannot write " + fileName + "\n");
        }
    }

    @SuppressWarnings({ "unchecked", "resource" })
    public void open(String fileName) throws CarException
    {
        FileInputStream inputFile;

        try
        {
            inputFile = new FileInputStream(fileName);
        }
        catch (FileNotFoundException e)
        {
            throw new CarException("\nCannot open " + fileName + "\n");
        }

        ObjectInputStream fleetFile;

        try
        {
            fleetFile = new ObjectInputStream(inputFile);
            regNumbers = (ArrayList<String>)fleetFile.readObject();
            fleet = (ArrayList<StaffCar>)fleetFile.readObject();
        }
        catch (IOException io)
        {
            throw new CarException("\nError reading from " + fileName + "\n");
        }
        catch (ClassNotFoundException e)
        {
            throw new CarException("\nError reading from " + fileName + "\n");
        }

        try
        {
            fleetFile.close();
        }
        catch (IOException io)
        {
            throw new CarException("\nCannot close " + fileName + "\n");
        }
    }
}

我很抱歉为我倾倒了一堆代码,我知道这是不好的做法,我试图尽可能地压缩代码,但我觉得这是我的所有相关代码问题

就像我说的,我不明白为什么简单添加方法会导致此问题。

修改

Main上课

public class Main 
{   
    // new container
    static Fleet fleet = new Fleet();

    // initialise car object
    static StaffCar car;

    // programme loop variable
    static boolean state = false;

    String fileName;

    public static void main(String[] args) throws CarException
    {
        start();

        // programme loop
        while (!state) 
        {
            try 
            {
                // menu option variable
                String option;

                //displays menu to user and takes in input
                option = Console.askString("Menu:\n1 Add a car\n2 Display all car information\n3 Find a car\n4 Borrow a car\n5 Return a car\n6 Exit\n\n");
                //removes white spaces
                option = option.trim();

                //switch to handle user request
                switch (option) 
                {
                //if option 1
                case "1":
                    //call static add car method
                    addMethod();
                    break;
                //if option 2
                case "2":
                    //call static print car method
                    displayMethod();
                    break;
                //..option 3
                case "3":
                    //call static find car method
                    findMethod();
                    break;
                //..option 4
                case "4":
                    borrowMethod();
                    break;
                case "5":
                    //returnMethod();
                    break;
                case "6":
                    //call static quit method
                    quitMethod();
                    break;
                default:
                    System.out.println();

                    System.out.println("Invalid option.");

                    System.out.println();
                    break;
                }
            }
            catch (CarException c)
            {
                System.out.println(c.getMessage());
            }
        }
    }

    public static void start()
        {
            try
            {
                fleet.open("fleet.uwl");
            }
            catch (CarException e)
            {
                //System.out.println("\nFile not created yet!\n");
            }
        }

    //static menu method to print cars
    public static void displayMethod() throws CarException
    {
        System.out.println();

        //call printCars method
        fleet.printCars();

        System.out.println();
     }

}

1 个答案:

答案 0 :(得分:3)

您使用序列化保存了StaffCar的实例,然后更改了StaffCar类,并且无法再次读取已保存的StaffCar。

那是因为,如果你没有在你的类中指定serialVersionUID,JVM会根据类的布局(字段,方法等)为你计算一个。因此,要暂时解决您的问题,请检查读取文件时抛出的IOException,它应该告诉您保存的类的serialVersionUID是什么,并将以下内容添加到您的类中:

=INDEX(Level,-1+MATCH(TRUE,(Level="BR")*ROW(Level)>MATCH($C$1,Level,0),0))

其中XXX是保存对象中的串行版本UID,应在异常堆栈跟踪中提及。

但实际上,您遇到了这些问题,因为您选择使用序列化进行长期存储,这使您的代码很难发展。我不会这样做。相反,我会选择一种不那么脆弱且易于发展的格式,例如JSON或XML。定义文件应包含的内容,并生成包含此数据的JSON / XML文档。然后,无论您未来的casses是什么样子,只要您仍然可以解析JSON / XML,您就能够读取文件并获取保存的数据。