【问题标题】:Serializable in Java - JGraphT's Pair class - Should the type of instance members also implement Serializable?Java中的Serializable——JGraphT的Pair类——实例成员的类型是否也应该实现Serializable?
【发布时间】:2019-09-23 06:42:51
【问题描述】:

here,JGraphT 的Pair 类是Serializable。但是这个类包含的实例成员(firstsecond)并不强制为Serializable

这是当前实现的样子:

public class Pair<A, B>
    implements
    Serializable

我认为应该是这样的:

public class Pair<A extends Serializable, B extends Serializable>
    implements
    Serializable

我错过了什么吗?如果不是,那为什么不是 JGraphT 做的呢?

【问题讨论】:

    标签: java serializable jgrapht


    【解决方案1】:

    因为Serializable 仅在运行时相关。

    如果您想使用带有不可序列化元素的对,它将起作用,但如果尝试序列化将失败。但是,如果两个元素都是Serializable,那么无论通用边界如何,它们都会序列化。

    • Pair&lt;A extends Serializable, B extends Serializable&gt; implements Serializable => 始终可序列化,但不能用于不可序列化 A/B
    • Pair&lt;A, B&gt; implements Serializable => 如果 AB 在运行时恰好是 Serializable,则可序列化,但不能保证任何给定的 Pair
    • Pair&lt;A, B&gt; / Pair&lt;A extends Serializable, B extends Serializable&gt; => 无论类型参数如何,都永远不会可序列化,因为容器本身不是 Serializable

    【讨论】:

    • 即使你想要一个始终可序列化的PairAB静态 类型也不应该被强制为Serializable。 (您可以添加运行时检查,但这会很奇怪。)
    • @TomHawtin-tackline “即使我们希望 Pair 始终可序列化,那么 AB 也不应该强制成为 Serializable” - 为什么?我们说PairSerializable - 那么我们不应该强制AB 也应该是Serializable
    • 只有当类本身总是可序列化时,通过将其标记为可序列化而不指定它支持序列化的内容(如果内容支持)。在所有其他情况下,它就像类不可序列化一样工作。
    • @LavishKothari 以List 为例。不是Serializable,因为并非所有Lists 都是Serializable,但你不会想禁止AB 是某种List
    • @TomHawtin-tackline 感谢您提供的清晰示例。这对我的理解有很大帮助。
    【解决方案2】:

    这取决于Serializable 的使用情况。如果在框架内使用它来序列化 Pair 并在其他情况下崩溃,那么你是对的。

    如果这不是绝对要求,并且仅对实现者来说是可序列化的,则他们有责任确保这一点。

    例如,java.util.ArrayList 也实现了Serializable,尽管它不要求其成员可序列化。如果不是,序列化ArrayList 将失败。

    【讨论】:

      【解决方案3】:

      如果 A 和 B 将成为您班级的字段,那么它们应该是。

      ArrayList 和不可序列化内容的示例:

      测试类:

      public class NonSerialClass {
      
          private int i;
      
          public NonSerialClass(int i) {
              this.i = i;
          }
      
          @Override
          public String toString() {
              return "NonSerialClass{" +
                      "i=" + i +
                      '}';
          }
      }
      

      跑步者类:

      
              List<NonSerialClass> nonSerialClasses= new ArrayList<>();
      
              nonSerialClasses.add(new NonSerialClass(1));
      
              nonSerialClasses.add(new NonSerialClass(2));
      
              System.out.println("Before "+nonSerialClasses);
      
      
              ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
              ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
      
              oos.writeObject(nonSerialClasses);
              oos.flush();
              oos.close();
      
      
              ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
              ObjectInputStream oin = new ObjectInputStream(byteArrayInputStream);
              List ts = (List) oin.readObject();
              System.out.println("After "+ts);
      

      结果将是:

      Before [NonSerialClass{i=1}, NonSerialClass{i=2}]
      Exception in thread "main" java.io.NotSerializableException: ru.NonSerialClass
          at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
          at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
          at java.util.ArrayList.writeObject(ArrayList.java:766)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:498)
          at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
          at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
          at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
          at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
          at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
      

      【讨论】:

      • 请解释原因
      • 因为如果字段存在并且它不是瞬态的,它必须是可序列化的,以序列化整个对象
      • ArrayList 也是可序列化的,尽管它的成员不必是
      • 它不能被序列化(我也没说会),但是就像一个ArrayList,你可以使用一个Pair而不用序列化它。
      猜你喜欢
      • 2013-10-13
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2018-04-29
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2015-01-27
      相关资源
      最近更新 更多