ArrayList contains objects of the wrong type without explicit casting
Can anyone suggest how the given code could lead to such a problem, giving a random ClassCastException
one when the data is parsed from a file.
Details:
I have generic methods in a 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 a subclass with T = AdItem
as shown below:
AdItem adItem = getItem(position);
Everything works fine, but I was getting random production crash reports with an exception on the above line:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to .mypackage.AdItem
which obviously indicates that the list contains LinkedTreeMap
instead ofAdItem
The list is parsed from json and the code is type safe i.e. has no caste type, unverified warnings, etc.
What scripts ArrayList<AdItem>
contain LinkedTreeMap
runtime objects?
Except for the explicit uncontrolled / raw casting to Object
and from ArrayList
, which is not the case.
Parsing json from file:
ArrayList<AdItem> tempList = gson.fromJson(jsonReader, typeToken.getType());
Where
typeToken = new TypeToken<ArrayList<AdItem>>() {};
therefore tempList
should only contain AdItem
.
Can anyone explain how the ClassCastException can happen with the code above? Any additional details will be provided upon request.
source to share
By default, it will deserialize a JSON object into a LinkedHashMap if it doesn't recognize the provided type correctly.
Use the following code 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));
source to share