简体   繁体   中英

Generics - Calling a method with a generic parameter

I'm struggling here with generics.

To start things off, I want to return a list of objects via the following callback interface:

Callback interface:

public interface ArrayCallback<T> {
    public void onComplete(List<T> result);
}

So far so good. Now, using that callback, let's say I want to get a list of songs like so:

Using the callback to load a list of songs

public void loadSongs(ArrayCallback<Song> callback) {
    List<Song> songs = new ArrayList<Song>();
    ...
    callback.onComplete(songs);
}

No problems here. But now I want to load a list of SOME type of music item. It could be songs like before, but it could be albums, artists, etc. I've called the superclass of all of these types of things MusicItem . (Thus, Song has a super class of MusicItem ) Here's where it falls over.

Aaaaand the following doesn't work

public void loadMusicItems(MusicItemType type, ArrayCallback<? extends MusicItem> callback) {
    switch (type) {
        case Songs:
            loadSongs(callback);
            break;
        case Albums:
            loadAlbums(callback);
            break;
        default:
            break;
}

The problem is on the loadSongs(callback) line. I can't call this method because the types are different.

loadSongs(ArrayCallback<Song>) in MusicSource cannot be applied to loadSongs(ArrayCallback<capture<? extends MusicItem>>)

From my understanding I can't just use type T and need to use a wildcard because of covariance problems.

Is what I'm doing even possible? After writing this question out, I suppose arguably it would look a bit strange to the compiler if I'm suddenly restricting the bounds on a method call. I'd still be interested in working out what I'm doing wrong apart from perhaps a crazy method design.

Generic type will only be applied during the compilation ( to ensure type safety ) and will disappear during the run-time. So your implementation is actually violating the usage of generic type. Eg. You can pass a Song type enum with ArrayCallback of Album type. (imagine your loadSongs method will be then receiving an ArrayCallback of Album type. No way!)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM