Let's say I create a package process
with a public class Processor
, which has a constructor that expects a parameter of type Container<I>
. The class Container<I>
lies in a different package beyond my control and contains objects of arbitrary type I
. The container with the contained items is passed around between multiple classes of the package process
.
The items are processed via methods of the interface Processable
. They can be retrieved by the user of process
via the method getProcessedItem(Property property)
. This method returns a processed item with the property property
which is ensured to be contained by the passed container and can therefore be cast to the type parameter of the container.
example class:
package process;
import container.Container;
public class Processor<I extends Processable> {
private final ItemProcessor itemProcessor;
public Processor(Container<I> container){
this.itemProcessor = new ItemProcessor(container);
}
@SuppressWarnings("unchecked")
public I getProcessedItem(Property property){
return (I)itemProcessor.getProcessedItem(property);
}
}
Is it generally a good idea to make an unchecked type cast in a situation like this?
The only reasonable alternative I figured out so far is to make all classes in the package process
that have to hold a reference to the parameterized container (like ItemProcessor
) also generic just for the sake of preserving the type information needed in getProcessedItem(Property property)
.
EDIT: To clarify the functionality of the container class in my example:
I wanted the container class to represent some rather primitive collection-like class which should merely make it possible for the processor to retrieve the items it has to process.
That means ItemProcessor
and classes used by ItemProcessor
should be able to handle the processable items (once they are retrieved from the container)
as they like (e.g. store them in lists or other data structures). And finally it should be possible to request a processed item based on a certain processor-specific property. For example:
getProcessedItem(Property.MOST_RECENTLY_PROCESSED)
Like java's standard collection classes (e.g. ArrayList
) Container<I>
does not strictly guarantee that it only contains I
and its descendants. This means once an item of the container is used as a Processable
, while actually not being a Processable
, a cast exception occurs.
In the version of the Processor class above no exception is immediately thrown when an item requested via getProcessedItem
is not compatible to type I
(due to the unchecked cast). But also if I made ItemProcessor
generic (ItemProcessor<I>
) and made its getProcessedItem
return I instead of using the unchecked cast, no exception would be thrown at that point. Therefore I am also unsure if it would be better to make a runtime type check using a Class<I>
object in getProcessedItem
. The Class<I>
object would have to be explicitly served by the caller as a parameter or via the given container. I feel like it should not be the processor's concern to ensure that the items in the container are actually compatible with I
, because the processor is not responsible for the validness of the content of the given container.
I think your SuppressWarnings defeats the purpose of generics. What you should do is to make getProcessed item generic as well.