Reputation: 693
Following is my interface definition
interface IStorage {
<T extends ICommon> Collection<T> find(String name, boolean isExact);
}
And this is the implementation
Storage implements IStorage {
Collection<IOrganization> find(String name, boolean isExact) {
//some code
}
}
IOrganization is a subtype of ICommon.
Why do I still see an unchecked conversion warning ?
Upvotes: 1
Views: 204
Reputation: 122449
When you have a generic method like <T extends ICommon> Collection<T> find(...
, that means that the caller can ask for T to be anything they want. Which means that the method must work with any such type T, rather than be able to choose a specific T (what you seem to want to do). To demonstrate, your generic method allows the caller to say
IStorage obj = ...;
Collection<SomeRandomClassImplementingICommon> foo = obj.find(...);
but your Collection<IOrganization> find(...
method is not compatible with the above because it does not return type Collection<SomeRandomClassImplementingICommon>
.
Upvotes: 0
Reputation: 29878
If your interface's purpose is to define a find method with the arguments of String name, boolean isExact
that clients will be able to know what specific element of ICommon
is being returned (so that, for example, a client can just grab a Collection<IOrganization>
rather than a Collection<? extends ICommon>
, then your interface signature should be the following:
interface IStorage<T extends ICommon> {
Collection<T> find(String name, boolean isExact);
}
The implementation then changes to the following:
class Storage implements IStorage<IOrganization> {
Collection<IOrganization> find(String name, boolean isExact) {
return null; // whatever you would return.
}
}
Note that this is different in that you have defined an interface that declares a specific type to be returned via the find method, whereas previously, it can only be said that a type of ICommon or some unknown subtype was returned, so if you tried to cast to ICollection, the compiler couldn't verify that you could always do this (if you gave it an implementation that wasn't an ICollection, you may get a ClassCastException at runtime).
Upvotes: 1
Reputation: 51030
Keep the same signature while you define Storage
because you are still defining the method find
(and not using it):
Storage implements IStorage {
<T extends ICommon> Collection<T> find(String name, boolean isExact) {
//some code
}
}
You will specify the concrete type parameter when you actually invoke that generic method:
Storage s = new Storage();
s.<IOrganization>find("hello world", true);
But the parameter type T
that your introducing with <T extends ICommon>
in your generic method is of no use, since you don't have in the parameter list.
May be what you probably want is not a generic method. But something as follows:
interface IStorage {
public Collection<? extends ICommon> find(String name, boolean isExact);
}
//and
class Storage implements IStorage {
public Collection<IOrganization> find(String name, boolean isExact) {
//some code
}
}
//or
class Storage implements IStorage {
public Collection<? extends ICommon> find(String name, boolean isExact) {
//some code
}
}
Upvotes: 0
Reputation: 76908
Because as you have it written your interface specifies that find()
returns a Collection
of something that extends ICommon
Your implementation is returning a Collection
of a specific subclass of ICommon
. That's an unchecked conversion as far as the compiler can tell; what would happen if the Collection
actually contained some other subclass of ICommon
?
Upvotes: 3