【问题标题】:Deserialize subclasses without switch statements.反序列化没有 switch 语句的子类。
【发布时间】:2013-06-18 16:36:55
【问题描述】:

这更像是一个软件工程问题。 我有一个基类和扩展基类的类。我的目标是有一种更简洁的反序列化方式,比如字符串。我目前的解决方案是获取这个序列化的字符串,从预先确定的类型字段中提取“类型”,然后使用 switch 语句调用相应的子类的反序列化方法。有没有办法通过利用 Java 语言而不是 switch 语句来做到这一点?

public abstract class Base {
   String type;
}

public class A extends Base{
   public A(String serializedString){...}
}

public class B extends Base{
   public B(String serializedString){...}
}

public class AuxMethods {

   public static Base deserialize(String s){
       String type = extractType(s); // gets the type from the serialized object string
       Base deserialized = null;
       switch(type){
           case "A":
              deserialized = new A(s);
              break;
           case "B":
              deserialized = new B(s);
       }

  }

}

【问题讨论】:

  • 请注意,Java 支持多种自动序列化工具,例如 Java 对象序列化和 JAX-B。这些可能会减少您的工作量。
  • 我知道。我正在使用序列化工具,但出于示例目的,我进行了简化。
  • 好的。您使用的工具可以确定最佳解决方案。可能想要识别它。

标签: java polymorphism


【解决方案1】:

存储完整的类名(或者假设所有的类都在一个特定的包中),使用Class.forName,然后查找字符串构造函数来创建对象。

【讨论】:

  • Class.forName 进行反思。所以我认为他/她应该避免不必要地使用反射。
  • 你能解释一下'查找字符串构造函数'吗?
  • @BMT 反射正是您在这里所需要的,所以它不是“不必要的”。
  • @Realn0whereman 给定一个Class<?> actual = Class.forName(type);,调用actual.newInstance() 将需要一个默认构造函数,这不是你想要的。您想调用带有字符串的构造函数,因此您需要找到并调用它,如actual.getConstructor(String.class).newInstance(s)
  • @SebastianRedl 是的,这是一种方法。没有问题,但如果他不知道任何类,最好编写 switch 案例或条件案例。
【解决方案2】:

我认为您没有以正确的方式使用序列化。您应该简单地序列化Base 对象本身(使用ObjectOutputStream),而不是存储它指向的子类对象的字符串类名。 Java 会自动将实际的对象类型与序列化的子类对象一起存储。

这样,当您反序列化(使用ObjectInputStream)时,您会自动获得相同的子类对象,而无需使用switch-case 语句来确定Base 类引用应该指向哪个对象。

【讨论】:

  • 我正在使用可以被认为是 json 的专有序列化技术。不过,我会为自己的项目保留 Object...Stream。
猜你喜欢
  • 2016-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
  • 2017-07-15
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
相关资源
最近更新 更多