ArrayList contains wrong type objects without explicit raw-type casting

438 views Asked by At

Can anyone suggest how given code could possibly result in such issue, giving occasional ClassCastException when data is parsed from file.

Details :

I have a generic methods in superclass.

public T getItem(int position) {
     return mItems.get(position); // mItems is an ArrayList
}
// corresponding setter
public void setItems(List<T> items) {
    mItems = items;
    notifyDataSetChanged();
}

It is then used in subclass with T = AdItem as below :

AdItem adItem = getItem(position);

Everything works fine, but I got occasional production crash reports with exception at the above mentioned line:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to .mypackage.AdItem

which obviously indicates that list contains LinkedTreeMap instead of AdItem

The list is parsed from json, and the code is type safe, i.e. no raw type casting, unchecked warnings, etc.

What are scenarios for ArrayList<AdItem> to contain LinkedTreeMap objects runtime ?
Except for explicit unchecked/raw-type casting to Object and back to ArrayList which is not the case.

Parsing json from file :

ArrayList<AdItem> tempList = gson.fromJson(jsonReader, typeToken.getType());

where

typeToken = new TypeToken<ArrayList<AdItem>>() {};

so tempList should only contain AdItem.

Can anyone explain how ClassCastException could possibly happen with the code above ? Any extra details will be provided on request.

1

There are 1 answers

1
Prashant Kedia On

By default it deserialize a JSON object into a LinkedHashMap if it does not recognize the provided type properly.

Use code as give below to get the type and try again:

TypeFactory.defaultInstance().constructCollectionType(ArrayList.class,AdItem.class)

or

new ObjectMapper().getTypeFactory().constructCollectionType(ArrayList.class,AdItem.class) // In case you are using ObjectMapper

i.e.

ArrayList<AdItem> tempList = gson.fromJson(jsonReader, TypeFactory.defaultInstance().constructCollectionType(ArrayList.class,AdItem.class));