Let's say I have a set of sources that supply an array of tagged items where the type of the item varies from source to source. I want to create a default implementation of the source method, but I haven't been able to find a way to do so without getting a compiler warning about unchecked conversions.
To begin with, here's my generic tagged item:
public class TaggedItem<T> {
private final String tag;
private final T item;
public TaggedItem(String tag, T item) {
this.tag = tag;
this.item = item;
}
public String getTag() { return tag; }
public T getItem() { return item; }
}
and a sample concrete implementation where the item type is String
:
public class TaggedString extends TaggedItem<String> {
public TaggedString(String tag, String item) {
super(tag, item);
}
}
Now here's my generic source interface:
public interface ITaggedItemSource<T> {
default TaggedItem<T>[] getTaggedItems() {
return new TaggedItem[0]; // (1)
}
default TaggedItem<T>[] getTaggedItems(Class<TaggedItem<T>> clazz) {
return (TaggedItem<T>[])Array.newInstance(clazz, 0); // (2)
}
default List<TaggedItem<T>> getTaggedItemList() {
return new ArrayList<TaggedItem<T>>();
}
}
I began with the first method. However this causes the following compiler warning at (1)
:
Type safety: The expression of type TaggedItem[] needs unchecked conversion to conform to TaggedItem<T>[]
So I added the second method. However this causes the following compiler warning at (2)
Type safety: Unchecked cast from Object to TaggedItem<T>[]
Finally, for the third method, I converted my array to a List
and I was warning free.
For the record, here's an example of a concrete source.
public class TaggedStringSource implements ITaggedItemSource<String> {
@Override
public TaggedItem<String>[] getTaggedItems() {
TaggedString[] items = new TaggedString[1];
items[0] = new TaggedString("t1", "data");
return items;
}
@Override
public TaggedItem<String>[] getTaggedItems(Class<TaggedItem<String>> clazz) {
TaggedString[] items = new TaggedString[1];
items[0] = new TaggedString("t1", "data");
return items;
}
@Override
public List<TaggedItem<String>> getItemList() {
List<TaggedItem<String>> items = new ArrayList<>();
items.add(new TaggedString("t1", "data"));
return items;
}
I should note that both the default array and List
implementations work just fine despite the compiler warnings. (As you'd expect I suppose, after all, they're just warnings.)
My questions are:
- Is it possible to have a method that uses arrays that does not cause a warning? If so, how?
- Why is it possible to avoid a warning when using
Lists
?