2017-09-15 4 views
0

Lorsque je définis une méthode pour renvoyer une classe de type, ne devrais-je pas pouvoir remplacer la méthode par un type qui étend Base? Prenons l'exemple suivant:Méthodes génériques retournant une collection donnant un avertissement de type Diffusion non sécurisée

MultiEntryModel.java (classe parente)

protected abstract <T extends Model> List<T> getDataList(); 

ProgramData.java

public class ProgramData extends MultiEntryModel { 
    ... 
     @Override 
     protected List<Program> getDataList() { 
      return programs; 
     } 
} 

Program.java

public class Program extends Model { 
    ... 
} 

Je reçois un type dangereux lancer un avertissement dans Programs.java, même si je retourne une liste contenant des objets de type Program, qui étend le Mod el class, comme indiqué par la signature de la méthode dans la classe de base <T extends Model>. Pourquoi?

+0

Publier une complète exemple minimal reproduire le problème, ainsi que le message d'erreur exacte et complète. Il n'y a aucune distribution dans le code que vous avez posté. –

+0

Il n'y a pas de casting. L'avertissement apparaît dans Programs.java au point où la méthode est surchargée. – user1452030

Répondre

6
protected abstract <T extends Model> List<T> getDataList(); 

Cela signifie qu'une liste sera de retour qui doit être sans danger pour touteT. Par exemple:

List<SomeModel> someModelList = thing.getDataList(); 

Si la liste vous retournez est un List<Program>, cela va être dangereux - parce que vous pouvez ajouter un SomeModel dans cette liste, et/ou vous pouvez essayer d'obtenir un SomeModel de la liste. Si Program est un sous-type/supertype de Program, une seule de ces opérations est sûre; sinon, ils sont tous les deux dangereux.

Ne pas définir la variable de type sur la méthode - le mettre sur la classe:

abstract class TheClass<T extends Model> { 
    protected abstract List<T> getDataList(); 
} 

class ProgramClass extends TheClass<Program> { 
    protected List<Program> getDataList() { return programs; } 
} 
+1

Très intéressant et bien expliqué. Je vous remercie! :) – user1452030

+2

L'appelant n'est même pas lié aux sous-classes existantes de 'Model'. Avec une signature de ' Liste getDataList()', je pourrais même écrire, 'List list = getDataList(); ', vous attendant de retourner une liste d'instances de sous-classes' Model' qui implémentent 'ExecutorService' ... – Holger