2013-02-23 3 views
1

내가 추상 클래스동적으로 생성 된 클래스

public abstract class Base implements Serializable { 
    static final long serialVersionUID = 1; 
    public Base(int x) { ... } 
    public abstract void baseMethod(); 
} 

을 가지고 있다고 가정 직렬화하고 내가 동적

public class Temp { 
    public Base getBase() { 
     return new Base(2) { 

      static final long serialVersionUID = 1; 

      @Override 
      public void baseMethod() { .... } 
     }; 
    } 
} 

내가 동적으로 문자열에서 클래스 온도를 생성 할 수 오전 클래스를 생성하면, 호출 새 인스턴스를 만들고 기본 객체를 추출한 다음 Base를 확장하는 다른 인스턴스처럼 사용합니다. 직렬화 할 때 문제가 발생합니다. 동적 기본 Temp 클래스에서 추출한 Base 기본 개체를 serialize 할 수는 있지만 Temp가 더 이상 클래스 경로에 없기 때문에 나중에 다른 세션에서 deserialize 할 수 없습니다.

사람들이이 문제를 어떻게 생각합니까? 문제의 기본 객체를 Temp 클래스와 분리하여 가져 오는 방법이 있어야합니다 (기본 클래스를 추출한 후에는 신경 쓰지 않습니다). Base 개체는 Temp 클래스의 내용에 의존하지 않습니다.

+0

here를 볼 수 있습니다 자바 직렬화에 대해 더 알고'내가 문자열 dynamically'에서 클래스 온도를 생성 할 수 있어요. 어떻게'String'에서 Temp 객체를 생성하고 있습니까? –

+0

무엇을 직렬화 하시겠습니까? –

+0

@VishalK, OP에서 두 번째 코드 블록의 String을 .java 파일처럼 처리하고 클래스로 컴파일하는 다른 코드로 전달합니다. 그런 다음 클래스를 호출하고 필요한 것을 얻습니다. 이 모든 잘 작동합니다, Base 개체 반환 getBase()에 의해 문제없이 사용할 수 있습니다. – richard

답변

1

그것은 Base를 기록 있도록 Temp 객체에 writeReplace를 구현하는 시도하고 그것을 감싸는 Temp을 만들어 있도록 Base 객체에 readResolve를 구현합니다. Serializable contract을 참조하십시오.

코드는 다음과 유사합니다. 내가 실제로 이것을 테스트하지는 않았지만 꽤 가까이 있어야한다는 점에 유의하십시오.

public class Base implements Serializable { 
    // Existing members here 

    private Object readResolve() throws ObjectStreamException { 
     return new Temp(this); 
    } 
} 

public class Temp implements Serializable { 
    Base base; 

    public Temp(Base base) { 
     this.base = base; 
    } 

    // Other existing methods here 

    private Object writeReplace() throws ObjectStreamException { 
     return base; 
    } 
} 

나는이 두 클래스 사이에 불쾌한 순환 종속성을 소개 실현,하지만 난 다른 제안과 같은 외부 리더/라이터 방법을 제외하고,이 일을 다른 좋은 방법이 표시되지 않습니다. 이 접근법의 장점은 더 큰 객체 그래프의 일부로 Temp을 쓰는 것을 지원한다는 것입니다.

+0

하하, 이건 내 머리 위에 조금있다, 나는 약간의 연구를해야 할 것이다 ... – richard

+0

안녕 Eric Galluzzo. 나는 당신이 제안한 것을 구현하는 방법을 알아내는 데 어려움을 겪고있다. (겸손한 경제학자로서 나의 페이드 그레이드보다 조금 위에). 나는 당신이 염두에 두었던 것에서 좀 더 구체화 될 수 있다면 너무 많은 문제가 아닌지 궁금해했다. – richard

+0

코드 샘플을 추가 했으므로 도움이 되었으면한다! –

0

글쎄 우선 리차드가이 독특한 케이스를 가져 오는 데 정말 감사합니다. 여기에서 저는 문제를 해결하기위한 몇 가지 방법을 개발했습니다. 나는 이것이 당신이 익명의 클래스 인스턴스 비록

import java.io.*; 
abstract class Base implements Serializable 
{ 
    protected int x ; 
    private static final long serialVersionUID = 1L; 
    public Base(int x) { this.x = x; } 
    public abstract void baseMethod(); 
} 
class Temp implements Serializable 
{ 
    private static final long serialVersionUID = 2L;//Make Temp serializable also. 
    public Base getBase(int i) 
    { 
     Base base = new Base(i) 
     { 
      static final long serialVersionUID = 1L; 
      @Override 
      public void baseMethod() { System.out.println(x); } 
     }; 
     return base; 
    } 
} 
public class ReadWriteBaseObject 
{ 
    public static Base createBaseObject(int i) 
    { 
     Temp temp = new Temp();//You might be creating your Temp object here Dynamically.. 
     Base base = temp.getBase(i); 
     return base; 
    } 
    public static Base read() 
    { 
     ObjectInputStream oin = null; 
     try 
     { 
      FileInputStream fin = new FileInputStream("BASE.ser"); 
      oin = new ObjectInputStream(fin); 
      Base base = (Base)oin.readObject(); 
      return base; 
     } 
     catch (Exception ex) 
     { 
      ex.printStackTrace(); 
      return null; 
     } 
     finally 
     { 
      if (oin!=null) 
      { 
       try 
       { 
        oin.close(); 
       } 
       catch (Exception ex){} 
      } 
     } 
    } 
    public static void write(Base base) 
    { 
     if (base == null) 
     { 
      System.out.println("Can't write null"); 
      return; 
     } 
     ObjectOutputStream os = null; 
     try 
     { 
      FileOutputStream fos = new FileOutputStream("BASE.ser"); 
      os = new ObjectOutputStream(fos); 
      os.writeObject(base); 
      System.out.println("Wrote to file"); 
     } 
     catch (Exception ex) 
     { 
      ex.printStackTrace(); 
     } 
     finally 
     { 
      if (os!=null) 
      { 
       try 
       { 
        os.close(); 
       } 
       catch (Exception ex){} 
      } 
     } 
    } 
    public static void main(String st[]) 
    { 
     Base base = createBaseObject(45); 
     write(base); 
     Base obj = read(); 
     obj.baseMethod(); 
    } 
} 

편집
을 .: 성공적으로 직렬화 할 수 있지만 여전히 강하게 인한 여러 합병증에 자바에 의해 권장하지 않습니다 도움이 될 수 있기를 바랍니다. Here은 무엇 자바 국가의 공식 사이트 :

주 - 로컬 및 익명 클래스를 포함한 내부 클래스 ( 하지 정적 멤버 클래스는 즉, 중첩 된 클래스)의 직렬화가, 강력하게 여러 가지 이유로 권장하지 않습니다. 비 정적 컨텍스트에서 선언 된 내부 클래스 에는 암시 적 비 일시적인 참조를 포함하는 내부 클래스가 있으므로이 내부의 클래스 인스턴스를 serialize하면 연결된 외부의 클래스 인스턴스도 직렬화됩니다. 내부 클래스를 구현하기 위해 javac (또는 다른 자바 컴파일러)로 생성 된 합성 필드는 구현에 따라 다르며 컴파일러에 따라 다를 수 있습니다. 이러한 필드에서 의 차이는 호환성을 방해 할뿐만 아니라
충돌하는 기본 serialVersionUID 값이 될 수 있습니다. 로컬 및 익명 내부 클래스에 할당 된 이름도 구현에 따라 달라지며 이며 컴파일러에 따라 다를 수 있습니다. 내부 클래스는 컴파일 타임 상수 필드가 아닌 정적 멤버를 선언 할 수 없으므로 serialPersistentFields 메커니즘을 사용하여 serializable 필드를 지정할 수 없습니다. 마지막으로 외부 인스턴스와 연결된 내부 클래스는 0 인수 구성 자 ( 의 생성자)를 가지지 않으므로 이러한 내부 클래스는 포함 된 인스턴스를 앞에 붙인 매개 변수로 암시 적으로 수락합니다. 따라서 Externalizable을 구현할 수 없습니다. 그러나 위에 나열된 문제 중 중 하나가 정적 멤버 클래스에 적용됩니다.

당신이

+0

고마워요 VishalK - 제가 틀렸다고 정정했는데 비상용으로 시도 할 때 나중에 세션에서 클래스 패스에 Temp가 필요하지 않습니까? – richard

+0

@richard 네, 맞습니다 .. !! 출구가 있어야합니다. –

+0

VishalK - 음, 어쨌든 고마워! – richard

관련 문제