2012-09-26 2 views
5

Eclipse 3.4. Java niveau du compilateur 1.6 JRE IBM 1.6Référence de constructeur ambigu dans javac mais pas dans Eclipse

Nous avons une classe de bibliothèque que nous ne pouvons pas changer qui est de la forme.

import java.util.Hashtable; 
public class A extends Hashtable { 
    ... 
} 

Et nous avons construit une classe utilitaire pour fournir un accès facile à A.

public class B { 
    private A a; 
    public B() { 
    this.a = new A(); 
    } 
    public B(final A props) { 
    this.a = props; 
    } 
    public B(final Map<String, String> props) { 
    this(); 
    for (String key : props.keySet()) { 
     add(key, props.get(key)); 
    } 
    } 
    @SuppressWarnings("unchecked") 
    public B add(final String name, final Object value) { 
    a.put(name, value); 
    return this; 
    } 
} 

Le problème se produit lorsque nous essayons d'appeler l'un des constructeurs d'une autre classe.

public class C { 

    public void stuff() { 
    A a = new A(); 
    B b = new B(a);//Error in javac 
    } 
} 

Eclipse compile cela sans erreur, et quand il est compilé par javac ant et jenkins le compilateur donne une erreur comme suit.

reference to B is ambiguous, both method B(com.foo.A) in com.bar.B and method B(java.util.Map<java.lang.String,java.lang.String>) in com.bar.B match 
    [javac]   B b = new B(a); 

Cette erreur est-elle survenue dans javac? À mon avis, éclipse est correcte en sélectionnant la méthode plus spécifique.

+1

Etes-vous sûr d'utiliser le même JDK dans Eclipse que pour Java? – dbalakirev

+3

A étend 'HashTable'. Est-ce que ça devrait être "Hashtable"? –

+0

@David correct -> édité –

Répondre

0

Puisque HashTable implémente Map, il y a une ambiguïté. HThis réponse contient quelques idées de Goot:

Calling ambiguously overloaded constructor in Java

+0

Mais Hashtable est plus spécifique que Map donc il devrait être sélectionné sans ambiguïté. JLS -> http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#308804 Cela doit être un problème concernant les génériques déclarés sur la carte –

-1

Comme la classe A étend Hashtable et Hashtable s'implémente l'interface de la carte, de sorte que vous pouvez dire la classe A obtient les propriétés de la carte et il devient également carte.

Lorsque vous rencontrez public B(final A props) et public B(final Map<String, String> props) Il est comme vous avez un argument de carte dans les deux constructeurs.

C'est pourquoi cela vous donne une certaine ambiguïté.

+0

-1 Je ne sais pas pense que tu es l'explication est correcte. Il est parfaitement possible d'avoir des méthodes surchargées avec des paramètres qui sont des sous-types les uns des autres. Comme je l'ai dit dans la question Eclipse est capable de compiler cela sans problème. Le compilateur choisira la méthode plus spécifique basée sur le type déclaré du paramètre lors de l'exécution. Puisque Hashtable est plus spécifique que Map, il doit être sélectionné sans ambiguïté. JLS -> docs.oracle.com/javase/specs/jls/se5.0/html/... Ceci doit être un problème lié aux génériques déclarés sur la carte –

0

Le problème est qu'un constructeur accepte une table de hachage brute, tandis que l'autre accepte une carte paramétrée. Les deux constructeurs sont applicables, mais la logique de désambiguïsation ne fonctionne pas dans ce cas, car, pour Java Language Specification - un constructeur serait plus spécifique que l'autre seulement si son argument était un sous-type (strict) de l'autre argument. Le sous-typage non contrôlé n'est pas autorisé pendant cette étape, d'où l'ambiguïté.

Questions connexes