Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generically specify a Serializable List

I have the following interface:

public interface Result<T extends Serializable> extends Serializable{
    T getResult();
}

With that interface, I can not define a variable of type

Result<List<Integer>>

because List is not serializable.

However, if I change the interface to this:

public interface Result<T> extends Serializable{
    T getResult();
}

It now becomes impossible to implement, with compile time checking, because there is no guarantee that T is serializable, and the whole point of the class is to store the result so that I can get it back later, possibly after a transfer over the internet.

My question is this, is there a way to declare a variable so that it is of two types, or is there some other way to do this that I am not seeing? So, maybe something like:

(List<Integer> extends Serializable) value = new ArrayList();

I am trying to put as much of the burden of this problem on the implementation, so that future consumers of this interface are unaware of the problem.

Thanks for your help!

Here is a more detailed example of what I am trying to do: I am calling a server, The result of which I want to store in a result object, but I do not want to have to deal with casting. So, each method that can be called on the server will define the type of the result by using generics. This result object will also store other meta-data about the result, for example maybe there was too much information to return. In many cases I want to use a list, but the List interface is not serializable, although many of the implementations are.

So, how to I specify that the type used must be Serializable, but still allow for a List(and not a specific implementation of List) to be used?

like image 345
Megamug Avatar asked Jan 20 '09 16:01

Megamug


People also ask

How do you make a List Serializable?

In Java, the ArrayList class implements a Serializable interface by default i.e., ArrayList is by default serialized. We can just use the ObjectOutputStream directly to serialize it.

Is it possible to declare a generic type that implements Serializable and List?

because List is not serializable. It now becomes impossible to implement, with compile time checking, because there is no guarantee that T is serializable, and the whole point of the class is to store the result so that I can get it back later, possibly after a transfer over the internet.

How do I prevent some data from getting serialized?

You can prevent member variables from being serialized by marking them with the NonSerialized attribute as follows. If possible, make an object that could contain security-sensitive data nonserializable. If the object must be serialized, apply the NonSerialized attribute to specific fields that store sensitive data.

Does List implement Serializable?

As pointed out already, most standard implementations of List are serializable. However you have to ensure that the objects referenced/contained within the list are also serializable. As pointed out already, List is an interface that does not extend Serializable or any interface that does so.


1 Answers

You need to declare your variable type as Result<? extends List<Integer>>.

The type checking knows that List isn't serializable, but a subtype of List can be serializable.

Here is some sample code. The interface implementation was just done with anonymous inner classes. You can see that the getResult will return a List<Integer> on the 2nd object

   Result<Integer> res = new Result<Integer>() {

        Integer myInteger;

        private static final long serialVersionUID = 1L;

        @Override
        public Integer getResult() {
            return myInteger;
        }

        @Override
        public void addResult(Integer input) {
            this.myInteger = input;
        }
    };

    Integer check = res.getResult();


    Result<? extends List<Integer>> res2 = new Result<ArrayList<Integer>>() {

        ArrayList<Integer> myList;

        private static final long serialVersionUID = 1L;

        @Override
        public ArrayList<Integer> getResult() {
            return myList;
        }

        @Override 
        public void addResult(ArrayList<Integer> input) {
            this.myList = input;
        }

    };

    List<Integer> check2 = res2.getResult();

Edit: Made the example more complete by implementing a void addResult(T input) interface method

like image 105
Patrick Avatar answered Oct 04 '22 01:10

Patrick