简体   繁体   中英

How to address unchecked cast Object to ArrayList<Vehicle>

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

first code excerpt your cast with generic (ArrayList) second code excerpt your cast without generic. cast is a runtime check - java compiler does type erasure, and at runtime there's actually no difference between a List<Vehicle> and List<Car>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM