2010-10-01 29 views
6

je le code de test suivant:Impossible de compiler une classe qui implémente une interface sans paramètre de type

public interface Container<I> { 
    public void addClass(Class<?> clazz); 
} 

public class MyContainer implements Container { 
    public void addClass(Class<?> clazz) {} 
} 

et je reçois l'erreur suivante lorsque vous essayez de compiler ces deux classes:

MyContainer. java: 1: MyContainer n'est pas abstraite et ne remplace pas la méthode abstraite addClass (java.lang.Class) dans le conteneur

Si j'ajoute un type à l'interfac conteneur e dans MyContainer (comme <Object>), je ne reçois pas l'erreur. Le problème est que j'introduis le paramètre type à Container, qui fait partie de l'API publique, donc pour la compatibilité, je ne peux pas avoir toutes les classes d'implémentation incapables de compiler.

Vous avez des idées? Est-ce un problème d'effacement de type? Y at-il un travail autour?

Répondre

7

Je pense que le problème est que si vous utilisez des types bruts n'importe où dans la déclaration de classe, vous sortez en quelque sorte des génériques. Cela fonctionnera donc - notez le changement de paramètre.

public class MyContainer implements Container { 
    public void addClass(Class clazz) {} 
} 

De section 4.8 of the JLS:

Les superclasses (respectivement, superinterfaces) d'un type sont les premières ratures de superclasses (superinterfaces) de l'un de ses invocations paramétrées.

Je crois qui est le bit correspondant ... l'effacement de Container<T>.addClass(Class<?> clazz) est addClass(Class clazz).

Mais oui, à la base, sauf s'il s'agit d'un véritable code existant, vous devriez envisager d'introduire un paramètre de type dans une interface comme changement de rupture.

+0

@ élaboration Skeet- serait helpful..TIA – hakish

+0

que je vois, je vous remercie Jon. Accepté. –

3

Se débarrasser si les <?> résout le problème:

public void addClass(Class clazz) {} 

Le message d'erreur n'est pas très descriptif:

choc Nom: La méthode addClass (classe) de type MyContainer a le même effacement, addClass (Class) de type Container mais ne le remplace pas

Cela signifie que vos deux méthodes sont les mêmes lorsque le Les types eir sont effacés, mais la méthode de la sous-classe n'implémente/ne remplace pas celle de la superclasse/interface.Cela n'a pas beaucoup de sens, et je suppose que c'est parce que vous avez choisi de ne pas utiliser de génériques dans votre sous-classe, vous devez vous y tenir (et non pas paramétrer Class)

3

Si votre cours utilise des génériques alors une solution simple serait de le faire:

interface Container<I> { 
    public void addClass(Class<?> clazz); 
} 

class MyContainer<I> implements Container<I> { 
    public void addClass(Class<?> clazz) {} 
} 

Ou si vous connaissez déjà le type de conteneur que vous avez,

class MyContainer implements Container<ContainerType> { 
    public void addClass(Class<?> clazz) {} 
} 

Si votre classe n'utilise pas Generics (avant la version 1.5), vous pouvez avez pas la partie <?>. Donc, il n'y aura pas de réel problème ici.

class MyContainer implements Container { 
    public void addClass(Class clazz) {} 
} 
0

La mise en œuvre de votre interface comme suit devrait fonctionner (selon l'effacement de type):

public class MyContainer implements Container { 
    public void addClass(Class clazz) {} 
}