Why do I get a Type safety warning here? (generics)
I lately wanted to learn more about generic methods and created several examples, but the following type safety is not clear to me. Here an example:
public class GeneralMethod
{
public static void main( String[] args )
{
Repository rep = new Repository();
Set<ConcreteObject> set = rep.getObject();
}
}
abstract class AbstractRepository
{
public abstract <T extends SuperObject> Set<T> getObject();
}
class Repository extends AbstractRepository
{
@Override
public Set<ConcreteObject> getObject() //<- Type safety!
{
return new HashSet<ConcreteObject>();
}
}
abstract class SuperObject
{
}
class ConcreteObject extends SuperObject
{
}
Following Type safety comes up in Reposit开发者_Python百科ory.class
in eclipse:
Type safety: The return type Set < ConcreteObject > for getObject() from the type Repository needs checked conversion to conform to Set < SuperObject > from the type AbstractRepository
Why does the compiler want to conform to Set < SuperObject > instead of Set < T extends Superobject >
?
How would you tell every Repository to implement a getObject()
method with its own type with only using generics in method signature? (meaning without defining the generic in class signature).
thank you, ymene
How would you tell every Repository to implement a getObject() method with its own type with only using generics in method signature? (meaning without defining the generic in class signature).
You cannot. When you say "it's own type", you would be referring to the generic type of the Repository subclass - which doesn't exist unless you are doing something like FooRepository extends AbstractRepository<Foo>
.
In this situation, I would simply make the abstract class generic:
public abstract class AbstractRepository<T extends SuperObject>
abstract Set<T> getObjects();
}
BTW, an abstract class with no non-abstract methods is probably better designed as an interface.
class AbstractRepository
Set<? extends SuperObject> getObject();
class Repository extends AbstractRepository
Set< ConcreteObject > getObject()
This works because Set<ConcreteObject>
is a subtype of Set<? extends SuperObject>
see also Overriding method with generic return type
AbstractRepository repository = new Repository();
Set<SuperObject> set = repository.getObject();
That should compile, but you would have a Set<ConcreteObject>
assigned to a Set<SuperObject>
variable.
Returns Set<? extends SuperObject>
should compile [not tested]. You might want to make the base class generic (or not return a set at all).
"Why does the compiler want to conform to Set < SuperObject > instead of Set < T extends Superobject > ? "
Because you told him so! The least type that could be substituted for T is, after all Superobject.
T extends SuperObject
bounds T
to any class that extends
(is a subclass) of SuperObject
. You are overriding AbstractRepository.getObject()
method so the method signature must be the same with it's parent class.
This should be valid (untested)
class Repository extends AbstractRepository
{
@Override
public Set<T extends SuperObject> getObject() //Valid
{
return new HashSet<ConcreteObject>();
}
}
精彩评论