2

From here, JGraphT's Pair class is Serializable. But the instance members this class contains (first and second) are not forced to be Serializable.

This is how the current implementation looks like:

public class Pair<A, B>
    implements
    Serializable

I think it should be something like:

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

Am I missing something? If not, then why is it not done by JGraphT?

Lavish Kothari
  • 2,211
  • 21
  • 29

3 Answers3

5

Because Serializable is only relevant during runtime.

If you want to use a pair with non-serializable elements it will work, except serialization will fail if it is attempted. However if both elements are Serializable then they will serialize regardless of the generic bounds.

  • Pair<A extends Serializable, B extends Serializable> implements Serializable => Always serializable, but unable to be used for non-serializable A/B
  • Pair<A, B> implements Serializable => Serializable if A and B happen to be Serializable during runtime, but no guarantees for any given Pair.
  • Pair<A, B> / Pair<A extends Serializable, B extends Serializable> => Would never be serializable regardless of type parameters since the container itself is not Serializable.
Kiskae
  • 24,655
  • 2
  • 77
  • 74
  • Even if you want an always serialisable `Pair` the *static* types of `A` and `B` shouldn't be forced to be `Serializable`. (You could add a runtime check, but that would be very odd.) – Tom Hawtin - tackline May 05 '19 at 11:57
  • 1
    @TomHawtin-tackline "even if we want `Pair` to be always serializable, then `A` and `B` shouldn't be forece to be `Serializable`" - Why? We are saying that `Pair` is `Serializable` - then shouldn't we force that `A` and `B` should also be `Serializable`? – Lavish Kothari May 05 '19 at 12:06
  • Only if the class itself is meant to be ALWAYS serializable, by marking it as serializable without specifying the contents it supports serialization if the contents do. In all other cases it works as if the class is not serializable. – Kiskae May 05 '19 at 12:24
  • 1
    @LavishKothari Consider `List` for instance. The isn't `Serializable` because not all `List`s are `Serializable`, but you wouldn't want to prohibit `A` or `B` being some kind of `List`. – Tom Hawtin - tackline May 05 '19 at 14:18
  • @TomHawtin-tackline Thanks for the clear example. It helped me a lot in understanding. – Lavish Kothari May 05 '19 at 14:27
0

It does depend on the usage of Serializable. If this is used inside the Framework to serialize a Pair and crash otherwise, then you're right.

If this is not an absolute requirement and it is only Serializeable for the implementors, it is their responsibility to ensure that.

For example, the java.util.ArrayList also implements Serializable, although it doesn't demand it's members to be serializable. Serializing an ArrayList will fail if they are not.

Dorian Gray
  • 2,913
  • 1
  • 9
  • 25
-1

If A & B will be fields of your class, so they should be.

example of ArrayList and not Serializable content:

TestClass:

public class NonSerialClass {

    private int i;

    public NonSerialClass(int i) {
        this.i = i;
    }

    @Override
    public String toString() {
        return "NonSerialClass{" +
                "i=" + i +
                '}';
    }
}

Runner class:


        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);

And result will be:

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)
Nikita
  • 94
  • 1
  • 3