J'ai la super-classe Foo. Et un bar de classe qui l'étend.
public class Bar extends Foo
Fonction dans Foo:
protected void saveAll(Collection<?> many)
Fonction dans le bar:
public void saveAll(Collection<MyClass> stuff) {
super.saveAll(stuff);
}
Obtenir une erreur:
Name clash: The method saveAll(Collection<MyClass>) of type Bar has the same erasure as saveAll(Collection<?>) of type Foo but does not override it.
Qu'est-ce que je fais mal?
Vous substituez la méthode saveAll
à un type incompatible. Peut-être que vous voulez faire quelque chose comme:
public class Bar extends Foo<MyClass>
Fonction dans Foo<E>
protected void saveAll(Collection<E> many)
et fonction dans le bar:
public void saveAll(Collection<MyClass> stuff) {
super.saveAll(stuff);
}
En raison de la fonctionnalité de suppression de type de Java, la machine virtuelle Java ne sera pas en mesure de savoir si c'est la méthode qui a le type paramétré MyClass ou la première à appeler.
Si cela est possible ou applicable, le motif le plus couramment utilisé pour éviter cela est de changer la classe Foo
pour avoir également un type paramétré:
public class Foo<T> {
protected void saveAll(Collection<T> many) {}
}
puis faites simplement en sorte que Bar implémente Foo
pour votre type spécifique:
public class Bar extends Foo<MyClass> {
public void saveAll(Collection<MyClass> many) {
super.saveAll(many);
}
}
Au moment de l'exécution, les types de paramètre sont remplacés par Object
. Donc saveAll(Collection<?>)
et saveAll(Collection<MyClass>)
sont transformés en saveAll(Collection)
. Ceci est un choc de noms . Regardez ici pour plus de détails.
Vous pourriez faire ceci:
public class Foo<T> {
protected void saveAll(Collection many) {
// do stuff
}
}
public class Bar extends Foo<MyClass> {
}
Lorsque les compilateurs compilent en code octet, un processus appelé Erasure se produit. Cela supprime les informations de type des collections. Je crois que cela fera manuellement les moulages, etc. dans le cadre du processus de génération du code octet. Si vous supprimez les parties génériques de votre classe (c'est-à-dire le <..>), vous verrez que vous avez deux méthodes saveAll. L'erreur est que vous avez deux enregistrer toutes les méthodes seront la même signature. Les collections ont un objet type dans le code d'octet.
Essayez de supprimer le <..> qui pourrait le rendre plus clair. Lorsque vous remettez le <...>, considérez le nom des méthodes. Si elles sont différentes, il devrait être compilé.
De plus, je ne pense pas qu'il s'agisse d'un problème d'hibernation, vous devez donc supprimer cette balise. C'est un problème générique Java que vous avez.
Ce que vous pouvez faire ici est de taper la classe
public class Bar extends Foo<MyClass>
puis avoir les types de méthode à T
public void saveAll(Collection<MyClass> stuff) {
super.saveAll(stuff);
}
et puis la déclaration de Foo serait quelque chose comme
public abstract class Bar extends Foo<T> {
public void saveAll(Collection<T> stuff) {
}
Vous venez de surcharger des méthodes avec différentes signatures.
La bonne idée est d’utiliser la règle PECS (Producer - Extends, Consumer - Super) décrite dans Effective Java Second Edition de Joshua Bloch.
selon cette règle, il devrait ressembler à ceci.
En classe Foo:
public class Foo<E>{
protected void saveAll(Collection<? super E> many){....}
protected void getAll(Collection<? extends E> many){....}
}
Bien que les réponses existantes soient correctes, cette erreur se produit facilement lorsque vous déclarez le type réel non pas dans la clause "extends
..." mais dans le nom de classe actuel:
Faux:
public class Bar<MyClass> extends Foo
{
...
}
Correct:
public class Bar extends Foo<MyClass>
{
...
}