For a class I was assigned to write code to read objects of the class Vehicle
using ObjectInputStream (in
). The objects are stored in an ArrayList called orders
.
SSCE:
// Read all orders
Object obj = in.readObject();
orders = (ArrayList<Vehicle>) obj;
However, the compiler complains:
MacBook:Homework Brienna$ javac Orders.java -Xlint:unchecked
Orders.java:152: warning: [unchecked] unchecked cast
orders = (ArrayList<Vehicle>) in.readObject();
^
required: ArrayList<Vehicle>
found: Object
1 warning
I always try to improve my code instead of ignoring or suppressing warnings. In this case, I have come up with a solution, but I'm trying to understand why it works, and if there is a better solution.
This update stops the warning:
// Read all orders, casting each order individually
Object obj = in.readObject();
ArrayList ar = (ArrayList) obj;
for (Object x : ar) {
orders.add((Vehicle) x);
}
Based on what I understand from what I've been reading, it works because (ArrayList<Vehicle>) obj
may throw an exception if not all the elements are Vehicle
. I am confused -- non-Vehicle objects can be added to the ArrayList even if its type parameter has been specified as Vehicle
? Also, is there a better solution, e.g. using instanceof
?
You were close. It is always safe to cast to ArrayList<?>
:
Object obj = in.readObject();
ArrayList<?> ar = (ArrayList<?>) obj;
orders.clear();
for (Object x : ar) {
orders.add((Vehicle) x);
}
You might even want to be extra safe and cast to something more generalized, like Iterable:
Object obj = in.readObject();
Iterable<?> ar = (Iterable<?>) obj;
orders = new ArrayList<>();
for (Object x : ar) {
orders.add((Vehicle) x);
}
If you have control over the objects which were originally serialized, there is a way to avoid the loop entirely: Use an array instead of a Collection. Array types are always a safe cast (if they don’t have a generic type themselves):
Object obj = in.readObject();
orders = new ArrayList<>(Arrays.asList((Vehicle[]) obj));