简体   繁体   English

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

[英]Why does my recursive method make my program throw an InvalidClassException?

In my program, I have a FacebookUser class that has an ArrayList of all of that user's friends.在我的程序中,我有一个 FacebookUser 类,该类具有该用户所有朋友的 ArrayList。 All of those friends may also have friends.所有这些朋友也可能有朋友。 I am using recursion to get a new ArrayList that contains all of the user's friends and all of the user's friends' friends and so on.我正在使用递归来获取一个新的 ArrayList,其中包含用户的所有朋友和用户的所有朋友的朋友等等。 I also serialized the FacebookUser class so I can save the data.我还序列化了 FacebookUser 类,以便我可以保存数据。 Without the new recursive method, I can serialize without error and the data persists over executions.如果没有新的递归方法,我可以无误地进行序列化,并且数据在执行过程中仍然存在。 With the recursive method, though, I get an InvalidClassException.但是,使用递归方法,我得到一个 InvalidClassException。 It shows that the exception is at the line that uses the ObjectInputStream to get the FacebookUser from memory.它表明异常发生在使用 ObjectInputStream 从内存中获取 FacebookUser 的那一行。

I'm not understanding why the new method is causing the exception to be thrown from another method.我不明白为什么新方法会导致从另一个方法抛出异常。 I believe the problem lies only in the FacebookUser.java class (since getRecommendations is recursive method) but I thought it'd be best to also show the UserAccount.java class since the former extends the latter.我相信问题仅在于 FacebookUser.java 类(因为 getRecommendations 是递归方法)但我认为最好同时显示 UserAccount.java 类,因为前者扩展了后者。 Any help will be appreciated.任何帮助将不胜感激。 Thank you.谢谢你。

Execution:执行:

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 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用户帐户.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;
            }
        }
    }
}

The exception suggests that the SerialVersionUID the JVM generated differs for some instances of the FacebookUser object.该异常表明 JVM 生成的 SerialVersionUID 与 FacebookUser 对象的某些实例不同。 If you make your class implement Serializable, it is highly recommended that you explicitly declare the SerialVersionUID variable to avoid exceptions like these.如果您让您的类实现 Serializable,强烈建议您显式声明 SerialVersionUID 变量以避免此类异常。 So in the FacebookUser class you should declare a variable like this:所以在 FacebookUser 类中你应该声明一个这样的变量:

private static final long serialVersionUID = 42L;

See this answer for more details.有关更多详细信息,请参阅答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM