简体   繁体   中英

Error in : java.io.InvalidClassException

I am working on this and getting this error cannot put my finger on the error:

This my class:

package stdaccmdmngmt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JOptionPane;

/**
 *
 * @author princess
 */
public class Student1 implements Serializable {

public static Set<Student1> listOfStudents = new HashSet<Student1>();    
public static File outFile = new File("StudentRegistry.dat"); 

// Data memebers 
private String studentID;
private String name;
private Date dateOfReg;

//Constructor 
Student1(String number,String name)
{
this.studentID = number;
this.name = name;
dateOfReg = new Date(); 
}


public String getName()
{
return name;
}

public String getStudentID()
{
return studentID;
}

public Date getDateOfReg()
{
return dateOfReg;
}

public void register() throws FileNotFoundException, IOException, ClassNotFoundException    
{ 
Set<Student1> sss = new HashSet<Student1>();    
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outFile));
oos.writeObject(sss);
oos.close();      
}

public static HashSet<Student> getListOfStudents() throws FileNotFoundException, IOException, ClassNotFoundException
{
HashSet ss;
File inFile = new File("StudentRegistry.dat");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(inFile));
Set<Student> aNewSet = (HashSet<Student>) ois.readObject();
return  (HashSet<Student>) aNewSet;
}

public static Student getStudentbyID(String a) throws FileNotFoundException, IOException, ClassNotFoundException
{
Set<Student> aNewSet = new HashSet<Student>();
aNewSet = Student.getListOfStudents();
Student result = null;

for (Student x :aNewSet)
{
        if (x.getStudentID().equalsIgnoreCase(a))
        {
             result = x;
             break;
        }
    }  
    if (result == null)
    {
        JOptionPane.showMessageDialog(null, "Apartment not found");
    }
    return result;    

}

    @Override
public String toString()
{
// include the code to retrieve assigned apartment    
return "Name: " + name +" StudentID: "+ studentID + " Registered On: " + dateOfReg;
}


    @Override
public boolean equals(Object another)
{
Student1 stud = (Student1)another;
return this.name.equals(stud.name)&& this.studentID.equals(stud.studentID);
}

    @Override
public int hashCode()
{
int hash = name.hashCode();
return hash;

}    
}

and this is the testing Class :

package stdaccmdmngmt;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author princess
 */
public class Test {

public static void main (String[]args) throws FileNotFoundException, ClassNotFoundException, IOException
{        
Student1 s = new Student1("12345","Sasha");   
        try {
            s.register();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }

Set<Student> nnn;
 nnn = Student.getListOfStudents();
for (Student x : nnn)

    System.out.println(x.toString());      

}

}
 * @author princess
 */
public class Student1 implements Serializable {

public static Set<Student1> listOfStudents = new HashSet<Student1>();    
public static File outFile = new File("StudentRegistry.dat"); 

// Data memebers 
private String studentID;
private String name;
private Date dateOfReg;

//Constructor 
Student1(String number,String name)
{
this.studentID = number;
this.name = name;
dateOfReg = new Date(); 
}


public String getName()
{
return name;
}

public String getStudentID()
{
return studentID;
}

public Date getDateOfReg()
{
return dateOfReg;
}

public void register() throws FileNotFoundException, IOException, ClassNotFoundException    
{ 
Set<Student1> sss = new HashSet<Student1>();    
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outFile));
oos.writeObject(sss);
oos.close();      
}

public static HashSet<Student> getListOfStudents() throws FileNotFoundException, IOException, ClassNotFoundException
{
HashSet ss;
File inFile = new File("StudentRegistry.dat");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(inFile));
Set<Student> aNewSet = (HashSet<Student>) ois.readObject();
return  (HashSet<Student>) aNewSet;
}

public static Student getStudentbyID(String a) throws FileNotFoundException, IOException, ClassNotFoundException
{
Set<Student> aNewSet = new HashSet<Student>();
aNewSet = Student.getListOfStudents();
Student result = null;

for (Student x :aNewSet)
{
        if (x.getStudentID().equalsIgnoreCase(a))
        {
             result = x;
             break;
        }
    }  
    if (result == null)
    {
        JOptionPane.showMessageDialog(null, "Apartment not found");
    }
    return result;    

}

    @Override
public String toString()
{
// include the code to retrieve assigned apartment    
return "Name: " + name +" StudentID: "+ studentID + " Registered On: " + dateOfReg;
}


    @Override
public boolean equals(Object another)
{
Student1 stud = (Student1)another;
return this.name.equals(stud.name)&& this.studentID.equals(stud.studentID);
}

    @Override
public int hashCode()
{
int hash = name.hashCode();
return hash;

}    
}

...........................

and I am getting this error :

run:
Exception in thread "main" java.io.InvalidClassException: stdaccmdmngmt.Student; local class incompatible: stream classdesc serialVersionUID = -3040096452457271695, local class serialVersionUID = -4849175799723926283
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1583)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at java.util.HashSet.readObject(HashSet.java:291)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at stdaccmdmngmt.Student.getListOfStudents(Student.java:76)
    at stdaccmdmngmt.Test.main(Test.java:34)
Java Result: 1
BUILD SUCCESSFUL (total time: 3 seconds)

Any help?

Thanks in advance :)

Yo've encountered one of the pitfalls of using Java serialization is a persistence framework (as opposed to a data format for communication). You persisted your student data, then changed the Student class. Now, when you try and read the persisted data it fails because basically, the two versions of the class do not match up. If you had manually specified a serialVersionUID on the student class the serialization framework would not have choked on reading the data file (not right away anyway).

But the root problem is that serialization is not the same as persistence - if you want to save your Student data then you need to select a framework for doing so that is less vulnerable to class file incompatibilities. I would recommend saving as a CSV file to start, and too take a look at a database solution down the line, if the project complexity warrants it.


* EDIT *

As a temporary fix you can try renaming the class back to Student and setting the serialVersionUID to what the serialization framework is expecting. This is not a garaunteed fix, it depends on how much the class has changed since it you created the file:

public class Student implements Serializable {
    public static final long serialVersionUID = -3040096452457271695L;

    // ...
}

Since its a requirement for your project to use object output stream, I will recommend implementing the Externalizable interface on your Student class, and implementing the methods to read/write it to an object output stream:

public class Student implements Serializable, Externalizable {
    public static final long serialVersionUID = -3040096452457271695L;
    // ...

   @Override
   public void writeExternal(ObjectOutput out) throws IOException {
      out.writeUTF(getStudentID());
      out.writeUTF(getName());
      // etc
   }

   @Override
   public void readExternal(ObjectInput in) throws IOException,
         ClassNotFoundException {
      setStudentID(in.readUTF());
      setName(in.readUTF());
      // etc
   }

   // ...
}

Taken from the Javadoc:

http://java.sun.com/j2se/1.4.2/docs/api/

public class InvalidClassException extends ObjectStreamException

Thrown when the Serialization runtime detects one of the following problems with a Class.

  • The serial version of the class does not match that of the class descriptor read from the stream
  • The class contains unknown datatypes
  • The class does not have an accessible no-arg constructor

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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