5
votes

Eclipse 3.4. Java compiler level 1.6 JRE IBM 1.6

We have a library class that we cannot change that is of the form.

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

And we have build a utility class to provide easy access to 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;
  }
}

The problem occurs when we try to call one of the constructors from another class.

public class C {

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

Eclipse compiles this without error, and when it is compiled through ant javac and jenkins the compiler gives an error like the following.

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);

Should this error happen in javac? In my view eclipse is correct in selecting the more specific method.

3
Are you sure you are using the same JDK inside Eclipse as for java?dbalakirev
A extends HashTable. Should that be Hashtable?David Grant
It works if you remove the generics from the second constructor i.e. change it to public B(final Map props). Not sure why. Sounds like a bug in javac.dogbane
@dave00 can't see this information on the jenkins dashboard or build output. I will check with one of the jenkins admins. This is the first ocurence of this kind of problem after about a year of builds, so I suspect they are the same.mR_fr0g
@dogbane Yes that is indeed the temp fix I have added to get our jenkins build working. Now to raise a bug.mR_fr0g

3 Answers

0
votes

Since HashTable implements Map, there is ambiguity. HThis answer contains some goot insights:

Calling ambiguously overloaded constructor in Java

0
votes

The problem is that one constructor accept a raw Hashtable, while the other accept a parameterized Map. Both constructors are applicable, however the disambiguation logic doesn't work in this case, as, per Java Language Specification - a constructor would be more specfic than the other one only if its argument was a (strict) subtype of the other argument. Unchecked subtyping is not allowed during this stage, hence the ambiguity.

-1
votes

As class A extends Hashtable and Hashtable itself implements Map interface, so you can say class A gets properties of Map and it also becomes Map.

When you are having public B(final A props) and public B(final Map<String, String> props) It is like you are having a map argument in both the constructors.

That's why it gives you ambiguity.