2

Uni의 OOP 과정에 대한 과제로 : 학생들이 성적을 볼 수있는 학교 등록부, 교사가 성적을 추가 할 수있는 학교 등록부 .Java 비교기를 사용하여 TreeMaps를 포함하는 객체를 직렬화 할 수 없습니다.

"base"클래스는 사용자 배열, 클래스 (학교 클래스와 같은) 및 수업 및 교사와 코스를 연결하는 TreeMap과 같이 사용되는 모든 클래스 (Java)를 포함하는 싱글 톤입니다.

수정 된 데이터를 저장하기 위해이 기본 클래스 (중앙)를 직렬화하려고합니다. 문제는 내가 내 수업의

java.io.NotSerializableException: liceu.Central$1 
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183) 
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) 
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:440) 
at java.util.TreeMap.writeObject(TreeMap.java:2265) 
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 java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) 
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495) 
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) 
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) 
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547) 
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508) 
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431) 
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177) 
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347) 
at liceu.Main.main(Main.java:31) 

모든 직렬화 구현이 예외를 얻을 수 있다는 것입니다, 그들은 (인스턴스 변수와 정적으로 getInstance 메소드를 가지고 싱글을 제외하고) 과도 또는 정적 필드가 없습니다.

게시물을 올리려면 많은 코드가 필요하므로 제출하기 전에 게시하여 과제를 무효화 할 위험이 있습니다. 오류를 격리하여 개념 증명을 시도했습니다.

public class Central implements Serializable 
{ 
    private ArrayList <User> users; 
    private ArrayList <Class> classess; 
    private TreeMap <Course, TreeMap <Class, Professor>> reunite; 
    private static Central instance = null; 

    private Central() 
    { 
     users = new ArrayList<>(); 
     classess = new ArrayList<>(); 
     reunite = new TreeMap<>(new Comparator<Student>(){ 
      @Override 
      public int compare(Student e1, Student e2) 
      { 
       return e1.getName().compareTo(e2.getName()); 
      } 
     }); 
    } 
} 

처음 두 개의 ArrayList 만 유지하면 직렬화 프로세스가 작동합니다. TreeMap에 문제가 있습니다.

TreeMap 클래스는 직렬화 가능합니까? (일반적으로) 익명 Comparator 때문입니까?

여기 직렬화

public class Main 
{ 
    public static void main(String args[]) 
    { 
     Central cent = Central.getInstance(); 
     FileOutputStream fos; 
     ObjectOutputStream oos; 

     cent.addUser(new Student(3,"id","pass","name","surname")); 
     cent.addUser(new Student(3,"id2","pass","name","surname")); 
     cent.addUser(new Student(3,"id1","pass","name","surname")); 
     try 
     { 
      fos = new FileOutputStream("save.txt"); 
      oos = new ObjectOutputStream(fos); 
      oos.writeObject(cent); 
     } 

     catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

맞춤형 비교기가 있습니까? 그렇다면 비교기를 직렬화해야합니다. 설명서 : http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html – gtgaxiola

+0

그의 맞춤 작성자가 이름없는 객체로 표시되는 것은 Central 클래스입니다. – bitli

+0

@gtgaxiola 아니요, it 익명 비교 자입니다. –

답변

12

트리 맵 그것이 키를 비교하기 위해 사용하는 상기 비교기에 대한 참조를 보유와 기본 클래스이다. 그리고 비교 자 (Comparator)는 직렬화 할 수없는 익명의 클래스의 인스턴스입니다. 그래서 당신은이 예외를 얻습니다.

최상위 또는 명명 된 내부 클래스에 익명 비교자를 리펙터링하여 Serializable도 구현합니다.

2

"Comparable에 implements implements"를 추가하면 문제가 해결됩니다.

+0

그럼, 그게 내가 한 짓이야 ... 3 년 전 xD. –

2

Serializable가 추가 바운드 캐스트 람다로 변환하는 것입니다 수하는 Comparator을 강제하는 또 다른 방법 : Java lambda expressions, casting, and Comparators : 여기

TreeMap<Integer, String> sortedMap = new TreeMap<>(
    (Comparator<Integer> & Serializable) (o1, o2) -> { 
     return o1.compareTo(o2); 
    } 
); 

는 설명이다.

+0

그 당시 Java 8을 사용할 수 없다고 생각합니다. –

+1

@SilentControl, 아마도. 그러나 사람들은 그 날에도 답을 찾고 있습니다.) – Vadzim