Sourajit Basak
Sourajit Basak

Reputation: 693

Unchecked conversion warning

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

Answers (4)

newacct
newacct

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

MetroidFan2002
MetroidFan2002

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

Bhesh Gurung
Bhesh Gurung

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

Brian Roach
Brian Roach

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

Related Questions