为什么在反序列化包含树形图的对象时会出现ClassCastException?

时间:2016-01-13 20:06:32

标签: java serialization deserialization treemap

当我从文件反序列化我的对象时,我得到一个ClassCastException。当我检查文件时,对象就在那里,所以我知道它正在被正确序列化。由于某种原因,代码在尝试检索对象时中断。这个想法是允许用户按日期检查他们在日志中记录的所有锻炼。此外,我已经尝试实现比较器,但我一直得到同样的错误,我完全没有想法。任何帮助将不胜感激。

以下是造成问题的代码:

case Logger.CHECK_KEY:
            //TODO

            try {

                workoutLog = (WorkoutLog) SerializationUtil.deserialize(file);
                System.out.println("Deserializing from:..." + file.getName());



            }

这是workoutLog类:

public class WorkoutLog implements Serializable{


public TreeMap < String , Workout > mWorkoutLog;

// thia is the actual Workoutlog

public WorkoutLog(){
    mWorkoutLog = new TreeMap<>();
}
//the string key will be the workouts formatted date
public TreeMap < String, Workout> getWorkoutLog(){
    return mWorkoutLog;
}

我包含了上下文代码的主体

package com.alejandro;


import com.alejandro.Utilities.SerializationUtil;
import com.alejandro.model.Exercise;
import com.alejandro.model.Workout;
import com.alejandro.model.WorkoutLog;
import com.sun.istack.internal.NotNull;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.TreeMap;

public class Logger {
public static final String COMPLETE_KEY = "COMPLETE";
public static final String INCOMPLETE_KEY = "INCOMPLETE";
public static final String ADD_KEY = "ADD";
public static final String CHECK_KEY = "CHECK";
public static final String EXIT_KEY = "EXIT";




public static void main(String[] args) throws IOException, ClassNotFoundException {
    Logger logger = new Logger();
    WorkoutLog workoutLog = new WorkoutLog();
    Workout workout = new Workout();
    File file = new File("workout.txt");

    //im going to need to ask if the user wants to add a workout, close the      program, or select a workout
    String userInput = checkUserIntention();

    //the switch statement goes through all the possible user inputs

    switch(userInput){
        case Logger.ADD_KEY:
            printInstructions();
            do{
                logger.promptForExerciseData(workout);

            }while(!checkIfUserIsDone());

            workoutLog.getWorkoutLog().put(workout.getDate(),workout);
            SerializationUtil.serialize(workoutLog,file);
            System.out.println("Workout saved in..." +file.getName());

            break;

        case Logger.CHECK_KEY:
            //TODO

            try {

                workoutLog = (WorkoutLog) SerializationUtil.deserialize(file);
                System.out.println("Deserializing from:..." + file.getName());
                System.out.println(workoutLog.getWorkoutLog().keySet()+"");


            } catch(EOFException e){
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }catch(ClassCastException E){
                E.printStackTrace();
            }
            break;


        case Logger.EXIT_KEY:
            System.out.println("\nExiting program...");
            break;

    }
}





//I'm using this method to explain to the user how to use the program
protected static void printInstructions(){

    System.out.println("\nWelcome to Mr.Strong!\n");
    System.out.println("This program was developed to help powerlifters keep a log of their lifts.\n");
    System.out.println("Because of this, the program will only recognize the following lifts:\n");
    System.out.println("Squat, Bench, Deadlift, Press.\n");
    System.out.println("The program is case-sensitive, make sure the information is entered as stated above.\n");

}



//this method asks the user for information about the lifts stores them in a workout object

//the methods used here are all organized throught the page, its just to keep things cleaner and separate
protected void promptForExerciseData(Workout workout){
    Exercise exercise = new Exercise();
    askForExerciseIdentity(exercise);
    askForNumsRelLifts(exercise);
    workout.getExerciseList().add(exercise);
}

//this will check to see if the user is done inputting the exercises he did, if he finished the program ends.
protected static boolean checkIfUserIsDone(){
    Scanner scanner = new Scanner(System.in);
    boolean isUserDone = false;
    System.out.println("\nEnter: 'complete'" + ", if you are done. " +
            "If not, enter:'incomplete " + ".\n");
    String answer = scanner.nextLine();
    if(answer.trim().toUpperCase().equals(Logger.COMPLETE_KEY)){
        isUserDone = true;
    } else if(answer.trim().toUpperCase().equals(Logger.INCOMPLETE_KEY)){
        isUserDone = false;
    } else{
        checkIfUserIsDone();
    }
    return isUserDone;
}

//check if user wants to add, review, or close


protected static String checkUserIntention(){
    String answer = "a";
    Scanner scanner = new Scanner(System.in);
    System.out.println("\nPlease choose an option:\n" +
            "1-) Add a workout. Enter 'Add'.\n" +
            "2-) Check a workout Enter 'Check'.\n" +
            "3-) Exit the program. Enter 'Exit'\n");
    answer = scanner.nextLine();
    if(answer.trim().toUpperCase().equals(Logger.ADD_KEY) ||
            answer.trim().toUpperCase().equals(Logger.CHECK_KEY)||
            answer.trim().toUpperCase().equals(Logger.EXIT_KEY)){
        return answer.toUpperCase();
    }else{
        System.out.println("Incorrect input.");
        checkUserIntention();
    }


    return answer;


}



//all of this part is asking for the exercise data



    //this is the part that asks for exercise id


protected void askForExerciseIdentity(Exercise exercise){
    Scanner scanner = new Scanner(System.in);
    do{
        System.out.println("\nEnter a lift:\n");
        String exerciseIdentity = scanner.nextLine();
        if(exerciseIdentity.equals(exercise.SQUAT_KEY)){
            exercise.setExerciseIdentity(exercise.SQUAT_KEY);
        }else if(exerciseIdentity.equals(exercise.PRESS_KEY)){
            exercise.setExerciseIdentity(exercise.PRESS_KEY);
        }else if(exerciseIdentity.equals(exercise.BENCH_KEY)){
            exercise.setExerciseIdentity(exercise.BENCH_KEY);
        }else if(exerciseIdentity.equals(exercise.DEADLIFT_KEY)){
            exercise.setExerciseIdentity(exercise.DEADLIFT_KEY);
        }else {
            exercise.setExerciseIdentity(null);
            System.out.println("Please enter a valid exercise.");
        }}while(exercise.getExerciseIdentity() == null);
}




    //this is the part that aks for numbers



protected void askForNumsRelLifts(Exercise exercise){
    exercise.setWeightUsed(askForWeightUsed());
    exercise.setNumOfReps(askForNumOfReps());
    exercise.setNumOfSets(askForNumOfSets());
}

protected double askForWeightUsed(){
    Scanner scanner = new Scanner(System.in);
    double weightUsed;
    do{
        try{
            System.out.println("\nEnter weight used:\n");

            weightUsed = Double.parseDouble(scanner.nextLine());

        }catch(NumberFormatException e){

            System.out.println("\nPlease enter a valid number\n");
            weightUsed = 0;

        }

    } while(weightUsed == 0);
    return weightUsed;
}

protected double askForNumOfSets(){
    Scanner scanner = new Scanner(System.in);
    double numOfSets;
    do{
        try{
            System.out.println("\nEnter sets done:\n");
            numOfSets = Double.parseDouble(scanner.nextLine());

        }catch(NumberFormatException e){
            System.out.println("\nPlease enter a valid number\n");
            numOfSets = 0;
        }

    }while(numOfSets == 0);
    return numOfSets;
}

protected double askForNumOfReps(){
    Scanner scanner = new Scanner(System.in);
    double reps;
    do{
        try{
            System.out.println("\nEnter reps done:\n");
            reps = Double.parseDouble(scanner.nextLine());
        } catch(NumberFormatException e){
            System.out.println("\nPlease enter a valid number\n");
            reps = 0;
        }

    }while(reps == 0);
    return reps;
}

}
这是锻炼包括:

public class Workout implements Serializable{
protected ArrayList<Exercise> mExerciseList;
protected Date mDateCreated;
public Workout(){
    mExerciseList = new ArrayList<>();
    mDateCreated = new Date();
}
public ArrayList<Exercise> getExerciseList(){
    return mExerciseList;
}
public String getDate(){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    return sdf.format(mDateCreated);
}}

这是seralizationutil:

import com.alejandro.model.WorkoutLog;

import java.io.*;


public class SerializationUtil{
public static Object deserialize(File filename) throws IOException, ClassNotFoundException{
    FileInputStream fis = new FileInputStream(filename);
    Object obj = new Object();
    BufferedInputStream bis = new BufferedInputStream(fis);
    ObjectInputStream ois = new ObjectInputStream(bis);
    while(fis.available()>0){
        obj = ois.readObject();

    }

    ois.close();
    return obj;

}
public static void serialize(Object object, File filename) throws IOException{
    FileOutputStream fos = new FileOutputStream(filename);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(object);
    oos.close();

}}

这是编译器给我的:

java.lang.ClassCastException: java.lang.Object cannot be cast to com.alejandro.model.WorkoutLog
at com.alejandro.Logger.main(Logger.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

1 个答案:

答案 0 :(得分:0)

试试这个简单的例子,我已经广泛修改了你的代码

还有一件事,我不知道你在SerializationUtil下有什么实现,所以我创建了自己的实现

我的示例没有任何问题

package week4;

import java.io.Serializable; import java.util.TreeMap;

public class WorkoutLog实现Serializable {     公共TreeMap&lt;字符串,锻炼&gt; mWorkoutLog;

// thia is the actual Workoutlog

public WorkoutLog(){
    mWorkoutLog = new TreeMap<>();
}
//the string key will be the workouts formatted date
public TreeMap < String, Workout> getWorkoutLog(){
    return mWorkoutLog;
}

}

package week4;

import java.io.Serializable;

public class Workout实现Serializable {

String date = "2016-01-13";

public String getDate() {
    return date;
}

public void setDate(String date) {
    this.date = date;
}

}

package week4;

import java.io.File; import java.io.IOException;

公共类TestWorkOut {

public static void main(String[] args) throws IOException, ClassNotFoundException {
    WorkoutLog workoutLog = new WorkoutLog();
    Workout workout = new Workout();
    /* I had path to workout.txt as D:\\workout.txt*/
    File file = new File("D:\\workout.txt");

    workoutLog.getWorkoutLog().put(workout.getDate(),workout);
    SerializationUtil.serialize(workoutLog,file);
    System.out.println("Workout saved in..." +file.getName());

    workoutLog = (WorkoutLog) SerializationUtil.deserialize(file);
    System.out.println("Deserializing from:..." + file.getName());
    System.out.println(workoutLog.getWorkoutLog().keySet()+"");

}

}

package week4;

import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;

public class SerializationUtil {

public static void serialize(WorkoutLog workoutLog, File filename) {

    FileOutputStream fos = null;
    ObjectOutputStream out = null;
    try {
      fos = new FileOutputStream(filename);
      out = new ObjectOutputStream(fos);
      out.writeObject(workoutLog);

      out.close();
    } catch (Exception ex) {
      ex.printStackTrace();
    }

}

public static WorkoutLog deserialize(File filename) {
    FileInputStream fis = null;
    ObjectInputStream in = null;
    WorkoutLog workout = null;
    try {
      fis = new FileInputStream(filename);
      in = new ObjectInputStream(fis);
      workout = (WorkoutLog) in.readObject();
      in.close();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return workout;
}

}

输出

锻炼保存在... workout.txt

反序列化:... workout.txt

[2016年1月13日]