JDK-6351601 : Can't deserialize object collections without "unchecked cast" warnings
  • Type: Enhancement
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-11-17
  • Updated: 2010-04-02
  • Resolved: 2005-11-17
Related Reports
Duplicate :  
Description
A DESCRIPTION OF THE REQUEST :
Collections of user-defined objects are used extremely frequently in Java.

The introduction of generics in Java 1.5 (aka 5.0) has created the "unchecked cast" warning to help identify code which is not type-safe.  In concept, this is a good thing.  The -Xlint option to javac is a critical component for ensuring correct behavior under 1.5.

However, as the simple sample code below shows, it is now impossible to "safely" deserialize such a common Java structure.  The sample code defines a trivial class, creates an ArrayList of such objects, and uses serialization to write and read back the ArrayList from a disk file.  Very basic stuff.

The problem is that the "unchecked cast" warning is unavoidable.  There is no way, in J2SE 1.5.0_01 and others, to avoid the warning when using -Xlint.

Of larger concern, however, is the lack of any mechanism to ensure type-safety in this case.

JUSTIFICATION :
Deserialization of collections of arbitrary objects is such a basic desire in a language such as Java that it simply must be accomodated somehow, preferably in as type-safe a manner as possible, and without having to defeat, ignore, or avoid compiler warnings.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I'm no expert on Java generics.  I'm just trying to get some real-world work done.

However, let me propose something that seems reasonable from my practical perspective:  something like java.lang.util.CheckedCollection() and friends.  I simply want a way to:

1) admit that I don't know what's coming in (who knows what java.io.ObjectInputStream.readObject() is returning to me); and to

2) declare the desired result (in my case that my "loosely typed" Collection object from readObject() has been checked and is can now be treated as a type-safe object).

I DON'T want to have to make another copy of the object.  In my case I could be deserializing megs or gigs of data.  There's likely to be nothing wrong with it, it just needs to be "blessed" at run-time by Java for type safety.

I also want any failure of the type-safety enforcement to fail here (not somewhere else in the code).
ACTUAL -
The code works but the warning is unavoidable, and type-safety is not assured.


---------- BEGIN SOURCE ----------
import java.io.*;
import java.util.*;

public class MyLong implements Serializable {

    private static final long serialVersionUID = 135238522108162360L;
    private long myValue = 0;

    public MyLong(int val) {
        myValue = val;
    }

    public long get() {
        return myValue;
    }

    public static void main(String args[]) throws Exception {

        // Create a collection of MyLong objects:
        int max = Integer.parseInt(args[0]);
        ArrayList<MyLong> lots = new ArrayList<MyLong>();
        for (int i = 0;  i < max;  ++i) {
            lots.add(new MyLong(i + 1));
        }

        // Serialize the collection to a file on disk:
        ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream("tmp.tmp"));
        oos.writeObject(lots);
        oos.flush();
        oos.close();

        // Deserialize the file on disk back to a collection:
        ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream("tmp.tmp"));
        ArrayList<MyLong> lots2 = (ArrayList<MyLong>) ois.readObject();
        ois.close();

        // Print the last value out as a sanity check:
        System.out.println(lots2.get(max - 1).get());
    }

}

COMPILE COMMAND AND COMPILE OUTPUT:

javac -Xlint MyLong.java
MyLong.java:36: warning: [unchecked] unchecked cast
found   : java.lang.Object
required: java.util.ArrayList<MyLong>
        ArrayList<MyLong> lots2 = (ArrayList<MyLong>) ois.readObject();
                                                                    ^
1 warning


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
1) Ignore warnings.  Doesn't work if your organization, like mine, requires "clean compiles" with maximum compiler checking (i.e. -Xlint) enabled.

2) Don't use -Xlint when compiling.  Doesn't work if your organization, like mine, requires "clean compiles" with maximum compiler checking (i.e. -Xlint) enabled.

See also:
http://forum.java.sun.com/thread.jspa?threadID=631940