복붙노트

[HADOOP] 익명 클래스의 NotSerializableException

HADOOP

익명 클래스의 NotSerializableException

항목 필터링을위한 인터페이스가 있습니다.

public interface KeyValFilter extends Serializable {
    public static final long serialVersionUID = 7069537470113689475L;
    public boolean acceptKey(String iKey, Iterable<String> iValues);
    public boolean acceptValue(String iKey, String value);
}

KeyValFilter 형의 멤버를 포함한 클래스 등이 있습니다.

public class KeyValFilterCollector extends KeyValCollectorSkeleton {
    private static final long serialVersionUID = -3364382369044221888L;
    KeyValFilter filter;
    public KeyValFilterCollector(KeyValFilter filter) {
        this.filter=filter;
    }
}

KeyValFilter를 구현하는 익명 클래스를 사용하여 KeyValFilterCollector를 시작하려고 할 때 :

new KeyValFilterCollector(new KeyValFilter() {
        private static final long serialVersionUID = 7069537470113689475L;
        public boolean acceptKey(String iKey, Iterable<String> iValues) {
            for (String value : iValues) {
                if (value.startsWith("1:"))
                        return true;
            }
            return false;
        }
        public boolean acceptValue(String iKey, String value) {
            return value.startsWith("0:");
        }
});

예외가 발생했습니다 : "main"스레드의 예외 java.io.NotSerializableException.

Serializable을 작성한 익명의 클래스는 어떻게 만들 수 있습니까?

해결법

  1. ==============================

    1.조슈아 블로흐 (Joshua Bloch)는 그의 책 Effective Java, Second Edition, Item 74 :

    조슈아 블로흐 (Joshua Bloch)는 그의 책 Effective Java, Second Edition, Item 74 :

  2. ==============================

    2.일반적으로, 익명 클래스를 직렬화 할 때 나타나는 문제는 둘러싸는 클래스가 직렬화되지 않는다는 것입니다. 그리고 저자는 익명 클래스를 직렬화하는 것이 그 둘러싸인 클래스를 직렬화하는 것을 인식하지 못했습니다.

    일반적으로, 익명 클래스를 직렬화 할 때 나타나는 문제는 둘러싸는 클래스가 직렬화되지 않는다는 것입니다. 그리고 저자는 익명 클래스를 직렬화하는 것이 그 둘러싸인 클래스를 직렬화하는 것을 인식하지 못했습니다.

    익명 클래스는 비 정적 인 내부 클래스입니다. 즉, 둘러싼 클래스의 인스턴스를 참조하는 숨겨진 필드가 있음을 의미합니다. 새 KeyValFilter () {...}를 명시 적으로 정규화하지 않고 (예 : something.new KeyValFilter () {...}) 새 클래스를 만들면 내포 클래스의 인스턴스로 암시 적으로 사용됩니다. this.new KeyValFilter () (...})를 수행하십시오. 따라서 익명 클래스를 직렬화 할 때는 모든 필드를 serialize해야하며 그 중 하나는 클래스를 묶는 인스턴스이며 직렬화 할 수 있어야합니다.

    둘러싸는 클래스의 필드 나 메서드를 사용할 필요가없는 경우 대신 정적 인 내부 클래스를 사용해야합니다. (그러나 그것은 익명이거나 메소드 내부에 정의 될 수 없습니다.)

  3. ==============================

    3.익명의 클래스를 직렬화 가능이라고 선언 할 수 있습니다 만, 그 클래스는 모든 필드가 직렬화 가능한 경우에만, 실제로는 직렬화 가능합니다.

    익명의 클래스를 직렬화 가능이라고 선언 할 수 있습니다 만, 그 클래스는 모든 필드가 직렬화 가능한 경우에만, 실제로는 직렬화 가능합니다.

    다음 예제를 참조하십시오.

    public static void main(String[] args) throws Exception {
        Object myObj = new Serializable() {
            private static final long serialVersionUID = 1L;
            private String str = "something";
            private Object ns = new Object(){};
        };
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(myObj);
        oos.close();
        System.out.println("Success!");
    }
    

    당신이 그 라인에 주석을 달았다면

    private Object ns = new Object(){};
    

    코드는 성공으로 끝나고, 그렇지 않으면 NotSerializableException이 발생합니다.

  4. from https://stackoverflow.com/questions/17804704/notserializableexception-on-anonymous-class by cc-by-sa and MIT license