为什么我的递归方法会使我的程序抛出InvalidClassException?

时间:2018-02-11 15:01:39

标签: java recursion serialization arraylist

在我的程序中,我有一个FacebookUser类,其中包含该用户所有朋友的ArrayList。所有这些朋友也可能有朋友。我正在使用递归来获取一个新的ArrayList,其中包含所有用户的朋友和所有用户的朋友的朋友等等。我还序列化了FacebookUser类,以便保存数据。如果没有新的递归方法,我可以无错误地序列化,并且数据会在执行过程中持续存在。但是,使用递归方法,我得到一个InvalidClassException。它显示异常位于使用ObjectInputStream从内存中获取FacebookUser的行。

我不明白为什么新方法导致从另一个方法抛出异常。我认为问题仅存在于FacebookUser.java类中(因为getRecommendations是递归方法)但我认为最好也显示UserAccount.java类,因为前者扩展了后者。任何帮助将不胜感激。谢谢。

执行:

Exception in thread "main" java.io.InvalidClassException: FacebookUser; local class incompatible: stream classdesc serialVersionUID = 4110981517967863740, local class serialVersionUID = 5032562666539812166
    at java.base/java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.base/java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.base/java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.base/java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.base/java.io.ObjectInputStream.readObject(Unknown Source)
    at FacebookUser.readFile(FacebookUser.java:157)
    at DriverClass.main(DriverClass.java:12)

FacebookUser.Java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class FacebookUser extends UserAccount implements Serializable{

    private String passwordHint;
    private ArrayList<FacebookUser> friends;
    public FacebookUser(String username, String password) {
        super(username, password);
        friends = new ArrayList<FacebookUser>();
    }

    @Override
    public void getPasswordHelp() {
        System.out.println("Password Hint: " + passwordHint);
    }

    public void getPasswordHelp(String username) {
        if (friends.size() == 0) {
            System.out.println("There is no user with that username.");
        } else {
            for (int i = 0; i < friends.size(); i++) {
                if (friends.get(i).toString().equals(username)) {
                    friends.get(i).getPasswordHelp();
                    break;
                }
                if (i == friends.size() - 1) {
                    System.out.println("There is no user with that username.");
                    break;
                }
            }
        }
    }

    void setPasswordHint(String hint) {
        passwordHint = hint;
    }

    void friend(FacebookUser newFriend) {
        if (friends.contains(newFriend)) {
            System.out.println("That person is already your friend.");
        } else {
            friends.add(newFriend);
        }
    }

    void friend(String username) {
        Scanner s = new Scanner(System.in);
        if (friends.size() == 0) {
            System.out.println("Please create a password: ");
            String password = s.nextLine();
            System.out.println("Please create a password hint: ");
            String passHint = s.nextLine();
            FacebookUser fbu = new FacebookUser(username, password);
            fbu.setPasswordHint(passHint);
            friends.add(fbu);
        } else {
            for (int i = 0; i < friends.size(); i++) {
                if (friends.get(i).toString().equals(username)) {
                    System.out.println("That person is already your friend.");
                    break;
                }
                if (i == friends.size() - 1) {
                    System.out.println("Please create a password: ");
                    String password = s.nextLine();
                    System.out.println("Please create a password hint: ");
                    String passHint = s.nextLine();
                    FacebookUser fbu = new FacebookUser(username, password);
                    fbu.setPasswordHint(passHint);
                    friends.add(fbu);
                    break;
                }
            }
        }
    }

    void defriend(FacebookUser formerFriend) {
        if (friends.contains(formerFriend)) {
            friends.remove(formerFriend);
        } else {
            System.out.println("That person is not your friend.");
        }

    }

    void defriend(String username) {
        Scanner s = new Scanner(System.in);
        if (friends.size() == 0) {
            System.out.println("That person is not your friend.");
        } else {
            for (int i = 0; i < friends.size(); i++) {
                if (friends.get(i).toString().equals(username)) {
                    System.out.println("Password for " + username + ": ");
                    String passw = s.nextLine();
                    if (friends.get(i).getPassword().equals(passw)) {
                        friends.remove(i);
                        break;
                    } else {
                        System.out.println("Incorrect Password");
                        break;
                    }
                }
                if (i == friends.size() - 1) {
                    System.out.println("That person is not your friend.");
                    break;
                }
            }
        }
    }

    ArrayList<FacebookUser> getRecommendations(FacebookUser friend) {
        ArrayList<FacebookUser> recFriends = new ArrayList<FacebookUser>();
        for (int i = 0; i < friend.getFriends().size(); i++) {
            for (int j = 0; j < recFriends.size(); j++) {                 
                for (int k = 0; k < recFriends.size(); k++) {               
                    if (recFriends.get(j).equals(recFriends.get(k))) {      
                        recFriends.remove(j);                           // This removes any duplicate friends so there won't be an infinite loop.
                        break;
                    }
                }
            }
            recFriends.addAll(friend.getFriends().get(i).getRecommendations(friend)); // This adds the friends' friends' friends and so on into the ArrayList.
        }
        return recFriends;
    }

    ArrayList<FacebookUser> getFriends() {
        ArrayList<FacebookUser> friendsCopy = new ArrayList<FacebookUser>();
        for (int i = 0; i < friends.size(); i++) {
            friendsCopy.add(friends.get(i));
        }
        Collections.sort(friendsCopy, new Comparator<FacebookUser>() {
            @Override
            public int compare(FacebookUser fb1, FacebookUser fb2) {
                return fb1.toString().compareToIgnoreCase(fb2.toString());
            }
        });
        return friendsCopy;
    }

    public static void writeToFile(FacebookUser facebookUser) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("FacebookUser.bin"));
        oos.writeObject(facebookUser);                                                              // This saves the data.
    }

    public static FacebookUser readFile() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("FacebookUser.bin"));

        FacebookUser facebookUser = (FacebookUser) ois.readObject();                               // This reads in the data which is called in the DriverClass class line 12.
        return facebookUser;
    }

}

UserAccount.java

import java.io.Serializable;

public abstract class UserAccount implements Serializable{

    private String username;
    private String password;
    private boolean active;

    public UserAccount(String username, String password) {
        this.username = username;
        this.password = password;
        active = true;
    }

    public boolean checkPassword(String password) {
        if (password.equals(this.password)) {
            return true;
        } else {
            return false;
        }
    }

    public void deactivateAccount() {
        active = false;
    }

    public String getPassword() {
        return password;
    }

    public String toString() {
        return username;
    }

    public boolean checkActive() {
        if (active == true) {
            return true;
        } else {
            return false;
        }
    }

    public abstract void getPasswordHelp();

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((username == null) ? 0 : username.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        UserAccount other = (UserAccount) obj;
        if (username == null) {
            if (other.username != null)
                return false;
        } else if (!username.equals(other.username))
            return false;
        return true;
    }

}

DriverClass.java

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;

public class DriverClass {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        int choice = 0;
        String username;
        FacebookUser fu0;
        try {
            fu0 = FacebookUser.readFile();
        } catch (FileNotFoundException e) {
            fu0 = new FacebookUser("Robert", "password1");
        }
        while (choice != 5) {
            System.out.println(
                    "1. List Users \n2. Add a User \n3. Delete a User \n4. Get Password Hint \n5. Get Recommendations \n6. Quit");
            Scanner s = new Scanner(System.in);
            choice = s.nextInt();

            switch (choice) {
            case 1:
                System.out.println(fu0.getFriends());
                break;
            case 2:
                System.out.println("Username: ");
                s.nextLine();
                username = s.nextLine();
                fu0.friend(username);
                break;
            case 3:
                System.out.println("Username: ");
                s.nextLine();
                username = s.nextLine();
                fu0.defriend(username);
                break;
            case 4:
                System.out.println("Username: ");
                s.nextLine();
                username = s.nextLine();
                fu0.getPasswordHelp(username);
                break;
            case 5:
                System.out.println(fu0.getRecommendations(fu0));
                break;
            case 6:
                FacebookUser.writeToFile(fu0);
                break;
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

该异常表明,JVM生成的SerialVersionUID对于FacebookUser对象的某些实例是不同的。如果您使类实现Serializable,强烈建议您显式声明SerialVersionUID变量以避免这些异常。 所以在FacebookUser类中你应该声明一个这样的变量:

private static final long serialVersionUID = 42L;

有关详细信息,请参阅enter image description here答案。