Java generics - cast to List <SomeType> gives an warning about an immediate warning when you click on SomeType not
Why is this:
public <T> List<byte[]> getData(T data) { Location loc = (Location) data; // ... }
does not generate any warnings until this:
public <T> List<byte[]> getData(T data) { List<ScanResult> scanRes = (List<ScanResult>) data; // ... }
generates Type safety: Unchecked cast from T to List<ScanResult>
?
How can I calm the warning?
How does this type of design declare smell?
public <T> List<byte[]> getData(T data)
is an interface method implemented in different classes with different data types. The first line of all implementations is listing.
You will receive a warning because listing (List<ScanResult>) data
not secure. Due to the type of erasure, the List<ScanResult>
will have a List
at runtime, so there will be no check of the real type regarding the type of the list item, That is, the execution will succeed even if you get List<String>
as a parameter, and later you will get a ClassCastException
when trying to access the list:
ScanResult result = data.get(0); // ClassCastException: String
One way to avoid this is to make a common interface:
public interface DataProvider<T> { public List<byte[]> getData(T data); }
And then define a specific type argument during implementation:
public class DataProviderFromLocation implements DataProvider<Location> { public List<byte[]> getData(Location data) { } } public class DataProviderFromScanResultList implements DataProvider<List<ScanResult>> { public List<byte[]> getData(List<ScanResult> data) { } }
I do not know if it is suitable for your needs.
From Angelika Langer Java Generics FAQ
We are ready to handle a ClassCastException when there is a listing expression in the source code, but we do not expect a ClassCastException when we retrieve an item from a list of strings. This kind of unexpected ClassCastException is considered a security breach. To draw attention to a potentially unsafe listing, the compiler generates a warning โunverifiedโ when it translates a dubious expression.
So the answer to my first question is that casting to SomeType
will not happen, and then if the classes are incompatible and List<ScanResult> scanRes = (List<ScanResult>) data;
which at runtime is just List scanRes = (List) data;
it will not work if data
is any implementation of List, but can lead to the creation of CCE in the remote and completely unrelated part of the code - it will be difficult to debug from here - therefore, a warning.
Another way to express this (by @erickson here ):
Performing your personal settings, you "comply with the warranty conditions" of Java generics: if a
ClassCastException
raised, it will be associated with the cast in the source code, and not with the invisible insert compiler.