从ObjectInputStream反序列化为其中一个子类

时间:2015-01-16 18:28:23

标签: android serialization xml-serialization objectinputstream simple-framework

我有一个名为Message的抽象类:

public abstract class Message
{
    public enum MsgType
    {
        TypeA, TypeB
    }

    public String Sender;
    public MsgType Type;
}

其中有两个子类:

public class MessageA extends Message
{
    public String A;

    public MessageA()
    {
        Type = MsgType.TypeA;
    }
}

public class MessageB extends Message
{
    public int B;

    public MessageB()
    {
        Type = MsgType.TypeB;
    }
}

我希望使用ObjectsInputStream库直接从MessageA反序列化对象,方法是实例化MessageBinputStream = new ObjectInputStream(clientSocket.getInputStream()); Message msg = serializer.read(Message.class, inputStream); // check whether it's MessageA or MessageB by checking Type ,具体取决于从流中读取哪一个。

我试过这样做:

MessageA

但它不起作用,因为编译器无法将MessageBMessage反序列化为{{1}}类。而且,我很确定我会丢失子类'这个过程中的领域。

有没有正确的方法呢?

2 个答案:

答案 0 :(得分:1)

public class Main {
    public static void main( String[] args ) throws Exception {
        Serializer serializer = new Persister();
        MessageB messageB = new MessageB( "example", 123 );
        File result = new File( "example.xml" );
        serializer.write( messageB, result );
        MessageB msgB = serializer.read( MessageB.class, result );
        System.out.println( msgB );
        try {
            if( serializer.validate( MessageA.class, result ) ){
                System.out.println( "valid for MessageA" );
            }
        } catch( Exception e ){
            System.out.println( "NOT valid for MessageA" );
        }
        try {
            if( serializer.validate( MessageB.class, result ) ){
                System.out.println( "valid for MessageB" );
            }
        } catch( Exception e ){
            System.out.println( "NOT valid for MessageB" );
        }
    }
}

public abstract class Message{
    public enum MsgType {
        TypeA, TypeB
   }
    @Element
    private String sender;
   @Element
    private MsgType type;
    protected Message(){
    }
    protected Message( String s, MsgType t ){
        sender = s;
        type = t;
    }
    public String getSender(){ return sender; }
    public MsgType getType(){ return type; }
    public String toString(){
        return "type=" + type + ", sender=" + sender;
    }
}

@Root
public class MessageA extends Message {
    @Element
    private String a;
    public MessageA(){
    }
    public MessageA( String s, String a ){
        super( s, MsgType.TypeA );
        this.a = a;
    }
    public String getA(){ return a; }
    public String toString(){
        return super.toString() + ", a=" + a;
    }
}
@Root
public class MessageB extends Message {
    @Element
    private int b;
    public MessageB(){
    }
    public MessageB( String s, int b ){
        super( s, MsgType.TypeA );
        this.b = b;
    }
    public int getB(){ return b; }
    public String toString(){
        return super.toString() + ", b=" + b;
    }
}

这非常有效。

type=TypeA, sender=example, b=123
NOT valid for MessageA
valid for MessageB

XML文件写为:

<messageB>
  <sender>example</sender>
  <type>TypeA</type>
  <b>123</b>
</messageB>

答案 1 :(得分:0)

为每个子类添加一个@Root(name =&#34; ...&#34;)注释

例如:

public interface StringOperation {
    String performOperation(String input);
}

@Root(name = "upperCaseStringOperation")
public class UpperCaseStringOperation implements StringOperation {
    public UpperCaseStringOperation() {
    }

    @Override
    public String performOperation(String input) {
        return (input == null) ? (null) : (input.toUpperCase());
    }
}

@Root(name = "lowerCaseStringOperation")
public class LowerCaseStringOperation implements StringOperation {
    public LowerCaseStringOperation() {
    }

    @Override
    public String performOperation(String input) {
        return (input == null) ? (null) : (input.toLowerCase());
    }
}

@Root(name = "noOpStringOperation")
public class NoOpStringOperation implements StringOperation {
    public NoOpStringOperation() {
    }

    @Override
    public String performOperation(String input) {
        return input;
    }
}

@Root
public class Data {

    @Element
    private String name;

    @Element
    private StringOperation nameOperation;

    @Element
    private String email;

    @Element
    private StringOperation emailOperation;

    public Data() {
        nameOperation = new NoOpStringOperation();
        emailOperation = new NoOpStringOperation();
    }

    public String getName() {
        return name;
    }

    public String getProcessedName() {
        return nameOperation.performOperation(getName());
    }

    public String getEmail() {
        return email;
    }

    public String getProcessedEmail() {
        return emailOperation.performOperation(getEmail());
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setNameOperation(StringOperation operation) {
        this.nameOperation = operation;
    }

    public void setEmailOperation(StringOperation operation) {
        this.emailOperation = operation;
    }

    @Override
    public String toString() {
        return String.format("Data(name = %s, processedName = %s, email = %s, processedEmail = %s)",
                             getName(),
                             getProcessedName(),
                             getEmail(),
                             getProcessedEmail());
    }
}

示例代码:

        Data before = new Data();
        before.setName("Joseph Wallflower");
        before.setNameOperation(new UpperCaseStringOperation());
        before.setEmail("Joseph.Wallflower@SomeCompany.com");
        before.setEmailOperation(new LowerCaseStringOperation());

        System.out.format("BEFORE: %s%n", before.toString());

        Serializer serializer = new Persister();
        File file = new File(System.getenv("USERPROFILE")+File.separator+"Documents"+File.separator+"simple.xml");
        serializer.write(before, file);

结果:

<data>
   <name>Joseph Wallflower</name>
   <nameOperation class="simplexml.UpperCaseStringOperation"/>
   <email>Joseph.Wallflower@SomeCompany.com</email>
   <emailOperation class="simplexml.LowerCaseStringOperation"/>
</data>