2013-10-16 1 views
4

Ce code compile bien sous Java 6, mais lors du passage à Java 7 résulte une erreur de compilation "référence à Foo est ambigu, les deux constructeurs < I, C > Foo (C) dans com.company.Foo et le constructeur <I> Foo (I) dans un match com.company.Foo »Constructeur ambigu (java 7) ... le seul moyen de contourner cela est un pattern Builder, non?

/** 
* Constructor A - acts on a Collection of Iterables 
*/ 
public <I extends Iterable<T>, C extends Collection<I>> Foo(C intervalSeries) { 
    initialize(intervalSeries); 
} 

/** 
* Constructor B - convenience constructor for callers who only have 1 Iterable 
*/ 
public <I extends Iterable<T>> Foo(I intervals) { 
    List<I> intervalSeries = newArrayList(1); 
    intervalSeries.add(intervals); 
    initialize(intervalSeries); 
} 

Je peux voir pourquoi (Collections sont Iterables). Je prévois d'écrire une classe d'aide Builder plutôt que de différencier les deux options de construction en fournissant une méthode de construction nommée différemment pour contourner cela, mais auparavant je pensais que je demanderais: Il n'y a pas de générique magique ou super incantation qui va fais-moi sortir de ça, non?

+0

Ce code fonctionne très bien dans mon IDE. Pouvez-vous s'il vous plaît montrer la partie du code qui appelle le constructeur et échoue? – TwoThe

+0

Essayé sous Java 7 sans problèmes. Il n'y a pas d'ambiguïté ici. Un constructeur s'attend à une 'Collection 'l'autre' Iterable'. Si une classe implémente les deux (comme avec tous les 'Collection's) le constructeur prenant un' Collection' sera utilisé comme il est plus spécifique. – Holger

Répondre

8

Vous utilisez trop les génériques.

Vous pouvez simplement prendre un Collection<I>, et toute sous-classe de celui-ci sera implicitement convertible à cette interface.

En fait, vous n'avez absolument pas besoin de paramètres de type; vous pouvez écrire

public Foo(Collection<? extends Iterable<T>> intervalSeries) 
public Foo(Iterable<T> intervals) 

Vous pouvez également changer T-? extends T.

+0

Vous avez totalement raison. J'ai hérité de ce code et supposé qu'il était "nécessairement fantaisiste" mais ce n'est pas le cas. Remplacer les constructeurs actuels avec votre suggestion est baller - résout le problème _and_ améliore le code. Merci, SLaks – user311121

0

Alors que @SLaks a la meilleure réponse, je voulais juste ajouter que l'utilisation de méthodes d'usine est une alternative possible à un constructeur, car vous pouvez les nommer. par exemple. (Je peux avoir les génériques mal)

public static <I extends Iterable<T>> Foo makeFooFromIterable(I intervals) { ... } 

public static <ignore the gererics part about C> Foo makeFooFromCollection(C c) { ... } 
Questions connexes