2012-02-23 2 views
6

복잡한 객체를 직렬화해야했지만 구성 요소 중 하나가 비 직렬화 (타사 그래프 객체)되었으므로이 Graph 클래스의 사용자 정의 직렬화 가능 버전을 생성했으며 Guava List transform을 사용하여 비 직렬화 가능 객체를 사용자 정의 객체로 변환합니다. serialization writeObject가 여전히 실패했습니다. 나는 이유를 알기에 관심을 가질 것인가? 필자의 가정은 Lists.transform이 원래의 객체에 대한 숨겨진 참조를 느슨하게 수행한다는 것입니다.Java 직렬화 문제, Guava 사용 중 Lists.transform

또한이 문제를 해결할 수있는 방법이 있습니까?

답변

11

Lists.transform()은 의심스러운만큼 느리게 수행합니다. 당신은

Lists.newArrayList(Lists.transform(...)) 

중 하나를 수행하거나, 당신은 불변의 버전을 원하는 경우,

ImmutableList.copyOf(Lists.transform(...)) 

을 한 다음 결과 목록을 직렬화 할 수있다.

+0

새로운 목록을 만들려면 @eneveu 대답을 참조하십시오. – Xaerxess

+2

OP는 fromList가 특히 직렬화 할 수없는 요소들로 가득하다고 말했습니다. –

+1

@Xaerness 댓글을 수정할 수 있습니까? enum 트릭 (@eneveu 응답)을 사용하여 직렬화 가능 목록을 가져올 수 없습니다. 이 대답은 질문과 관련하여 가장 유용합니다. –

1

Lists # transform에서 반환 된 목록을 serialize하려는 경우 List 자체는 이 아니며 Serializable입니다.

+1

왜 이것이 문제가됩니까? 직렬화 중에 고려되는 구현입니다. 그리고 Lists.transform()에 의해 반환 된 구현은 Serializable을 구현합니다. "반환 된 목록은 항상 Serializable을 구현하지만 fromList 및 함수가 serialize 될 때만 serialization이 성공합니다." ([javadoc] (http://docs.guava-libraries.googlecode.com/git-history/v11.0.1/javadoc/com/google/common/collect/Lists.html)에서) –

6

Lists.transform()은 원래 목록의 변형 된보기를 반환합니다. Lists.transform() javadoc에서 : fromList과 기능이 직렬화 때 반환 된 목록은 항상 직렬화 구현하지만

직렬화 에만 성공합니다.

변환 된보기를 serialize 할 때 실제로는 원래 목록과 함수를 직렬화합니다. 귀하의 경우 원래 목록이 직렬화 가능하지 않기 때문에 실패합니다 (직렬화 할 수없는 그래프 요소가 포함되어 있기 때문에). 그러나 함수가 직렬화를 구현하지 않기 때문에 실패 할 수도 있습니다.

자세히 알아보기, 간결함없이 직렬화 가능 기능을 만드는 것은 약간의 트릭입니다. 대신 일을 :

private static final class MyFunction extends Function<String, String> implements Serializable { 
    private static final MyFunction INSTANCE = new MyFunction(); 

    @Override 
    public String apply(String input) { 
     return "[" + input + "]"; 
    } 

    private Object readResolve() { 
     return INSTANCE; 
    } 
    private static final long serialVersionUID = 1; 
    } 

당신은 훨씬 덜 장황하고 (열거 직렬화 때문에) 무료 당신에게 직렬화를 얻을 열거 싱글 톤 패턴을 사용할 수 있습니다. 또한 함수가 싱글 톤인지 확인합니다.

// enum singleton pattern 
    private enum MyFunction implements Function<String, String> { 
    INSTANCE; 

    @Override 
    public String apply(String input) { 
     return "[" + input + "]"; 
    } 
    } 
+2

굉장 ... 효과적인 자바. 고맙습니다. –

+1

조슈아 블로흐 (Joshua Bloch)는 효과적인 자바에서 싱글 톤을 만드는 가장 좋은 방법이라고 설명합니다. 열거 형은 직렬화 가능하며 다양한 직렬화 해제 공격에 취약하지 않으며 JVM은 그 단일성을 보장합니다. Guava 라이브러리에서 패턴의 좋은 예를 찾을 수 있습니다. http://code.google.com/p/guava-library/source/browse/guava/src/com/google/common/base/Functions.java # 59 –

+0

EJ를 인용하고 Guava에서 좋은 패턴의 응용 프로그램에 대한 보너스 포인트입니다. 'fromList'가 직렬화되지 않기 때문에 유용합니다. –