views:

548

answers:

6

EDIT: This turned out not be a problem with the code at all, but with a bug in the Groovy Eclipse plugin (http://jira.codehaus.org/browse/GRECLIPSE-373)

Eclipse is giving me a weird error message about ambiguous types in a Java program and I really don't understand why. I have an interface that takes a generic parameter indicating what type of data it returns.

public interface InterfaceA<T> {
    T getData();
}

One of the implementations of it looks like this:

public class Impl<T extends AnotherClass> implements InterfaceA<Collection<T>> {
    public Collection<T> getData() {
       // get the data
    }
}

There is also a container for an InterfaceA

public class Container<T extends InterfaceA>
{
    private T a;

    public Container(T a) {
        this.a = a;
    }

    public T getA() {
        return a;
    }
}

Doing this causes the "getData is ambiguous" error.

Container<Impl<AnotherClass>> c = new Container(new Impl<AnotherClass>());
Collection<AnotherClass> coll = c.getA().getData();

I'm stumped on this one.

A: 

Your edited example works fine for me (JDK 1.5) with the exception, that you have to define the generic type on the constructor. Here is my complete working code:

public interface InterfaceA<T> {
    T getData();
}

public static class Impl<T extends Date> implements InterfaceA<Collection<T>> {
    public Collection<T> getData() {
        return null;
    }
}

public static class Container<T extends InterfaceA> {
    private T a;

    public Container(T a) {
        this.a = a;
    }

    public T getA() {
        return a;
    }

}

public static void main(String[] args) {
    Container<Impl<Date>> c = new Container<Impl<Date>>(new Impl<Date>());
    Collection<Date> coll = c.getA().getData();
}
Yishai
+2  A: 

Collection<T> getData() defined in Impl needs to be made public. If I do this the code compiles cleanly for me.

Adamski
Yes, sorry, that was a copy/paste error. I realized the code I posted was not in error, but I have updated with the code that is problematic.
Jeff Storey
A: 

What you have here seems legitimate. Perhaps Eclipse is showing an error it otherwise should not.

Go to Windows > Preferences > Java > Compiler > Errors/Warnings. In the "Generic Types" section, ensure that Eclipse isn't reporting an error for any of the operations listed (unless you want it too). I have all mine in that section set to "Warning". I would then try refreshing the project and restarting Eclipse.

Edit: After the updated post was made, I got a warning (not an error still) on the lines of usage, saying "Container is a raw type. References to generic type Container should be parameterized:". This can be fixed by:

Container<Impl<Date>> c = new Container<Impl<Date>>(new Impl<Date>());

(In my example, I'm using java.util.Date as in place of 'AnotherClass').

Cuga
typo. i have edited the question
Jeff Storey
It's not compiling cleanly for me... can't @Override an interface method implementation - it would have to be a superclass instead.
Nate
@Nate: you're using 1.5. Cuga is on 1.6.
A: 

[Edit to reflect updated question]

This shouldn't even compile as you are reducing the visibility of the method from public to package scope:

public class Impl<T extends AnotherClass> implements InterfaceA<Collection<T>> {
    Collection<T> getData() {
       // get the data
    }
}

And this still compiles for me (Eclispe 3.4, OS X, 1.5), so don't know what exactly is the issue:

package temp.tests;

import java.util.Collection;

public interface InterfaceA <T> {

    T getData();

    public static final class AnotherClass {}

    public static final class Impl<T extends AnotherClass> 
             implements InterfaceA<Collection<T>>
   {
        public Collection<T> getData () {
            return null;
        }
    }

    public static class Container<T extends InterfaceA>
    {
     private T a;
     public Container(T a) { this.a = a; }
     public T getA() { return a; }
    }

    public static final class Test {
     public static void main (String[] args) {
      Container<Impl<AnotherClass>> c = new Container(new Impl<AnotherClass>());
      Collection<AnotherClass> coll = c.getA().getData();
        }
    }
}
Thanks for looking into this. I posted an answer relating to the groovy/eclipse plugin. Turns out that was the culprit.
Jeff Storey
NP! You may want to add that as update to your question.
A: 

As other posters have said, I am not seeing this problem on Eclipse 3.5.0 running on JDK 1.6.0.14 (when fixing the reduced visibility of the getData() method).

I suggest doing a clean build (Project/Clean in Eclipse). Also, the Eclipse and Java version you are running might help.

-- Flaviu Cipcigan

Flaviu Cipcigan
I have updated the code to correctly illustrate the problem. It still breaks in eclipse, but seems to work if I compile with just javac.
Jeff Storey
+1  A: 

There appears to be a bug causing this from the groovy plugin. http://jira.codehaus.org/browse/GRECLIPSE-373. It is not a java problem at all. Thanks for the help and my apologies.

Jeff Storey
Can you edit the question to include this?
Matt Kane
I updated the question with that info at the top.
Jeff Storey