2

I'm stepping into an open source project, currently built using Maven2. I imported the project into Eclipse and this bit of code is giving me problems:

public static enum HierarchyType implements Function<MonetarySummary, SumOfMoney>, Predicate<Txaction> {
    EARNINGS {
        @Override
        public SumOfMoney apply(MonetarySummary summary) {
            return summary.getEarnings();
        }

        @Override
        public boolean apply(Txaction txaction) {
            return txaction.getAmount().signum() > 0;
        }
    },
    SPENDING {
        @Override
        public SumOfMoney apply(MonetarySummary summary) {
            return summary.getSpending();
        }

        @Override
        public boolean apply(Txaction txaction) {
            return txaction.getAmount().signum() < 0;
        }
    },
    NET {
        @Override
        public SumOfMoney apply(MonetarySummary summary) {
            return summary.getNet();
        }

        @Override
        public boolean apply(Txaction txaction) {
            return true;
        }
    }
}

Both Function and Predicate have apply methods (they're from the Google commons):

public interface Function<F, T> {
   T apply(@Nullable F from);
   ...
}

public interface Predicate<T> {
   boolean apply(@Nullable T input);
}

Here's the error I get, in Eclipse only:

Description Resource    Path    Location    Type
Name clash: The method apply(F) of type Function<F,T> has the same erasure as apply(T) of type Predicate<T> but does not override it    
Name clash: The method apply(F) of type Function<F,T> has the same erasure as apply(T) of type Predicate<T> but does not override it    
Name clash: The method apply(F) of type Function<F,T> has the same erasure as apply(T) of type Predicate<T> but does not override it    
Name clash: The method apply(T) of type Predicate<T> has the same erasure as apply(F) of type Function<F,T> but does not override it    
Name clash: The method apply(T) of type Predicate<T> has the same erasure as apply(F) of type Function<F,T> but does not override it    
Name clash: The method apply(T) of type Predicate<T> has the same erasure as apply(F) of type Function<F,T> but does not override it    

So, what's going on here? Is it a compiler flag?

For what it's worth, I'm running Eclipse 3.6, and maven is building using Java 1.6 on my OSX box:

Version: Helios Release
Build id: 20100617-1415

javac -version
javac 1.6.0_20
Chris R
  • 17,546
  • 23
  • 105
  • 172
  • What version of eclipse are you using, I tried something similar on eclipse 3.5 (by copying your example and changing the type parameters), and it didn't complain. – Andrei Fierbinteanu Jul 16 '10 at 13:29
  • I'm of the opinion that it's because `T` and `F` are non-specific (they could be the same thing), and then we run into this (http://stackoverflow.com/questions/3110014/is-this-valid-java) scenario (which seems to be quite popular lately, heh) again. But I didn't look into it enough to know for sure. – Tim Stone Jul 16 '10 at 13:32
  • I was thinking that might be the problem as well, especially if you are on eclipse 3.6, since it's my understanding that they're trying to make the compiler behave more like the Java 7 one, which apparently won't differentiate methods based on return type anymore. (according to this answer: http://stackoverflow.com/questions/3110014/is-this-valid-java/3117448#3117448 ) – Andrei Fierbinteanu Jul 16 '10 at 13:36
  • I wish they'd just add generics at the bytecode level already, and get rid of all these erasure problems. – Andrei Fierbinteanu Jul 16 '10 at 13:38
  • @Andrei: Yeah, it seems like it would simplify things a lot from the coding side in these edge cases. I wonder if there was a good technical reason for excluding them at the bytecode level (something I'm sure has been asked, and likely answered, many times before). – Tim Stone Jul 16 '10 at 14:04

3 Answers3

2

The problem here is that the erasures (everything between the angle brackets) are removed at compile time, making the parameters of the two apply methods identical. The return types differ, but the return type is not part of the method's signature in Java.

Sun's JDK and Eclipse up to 3.5 don't complain about this ambiguity (I think they do in fact look at the return types), but Eclipse 3.6 fixed that bug.

It should work in Eclipse 3.5, yet it's probably only a matter of time until other JDKs will fix this too, so I suggest implementing the methods explicitly or renaming one of them.

fhd
  • 3,998
  • 2
  • 23
  • 18
0

Yep, I think so. I haven't looked at this error in detail, but Eclipse lets you fine-tune a lot of error/warning messages for the Java compiler. You can try finding the one that applies to this message (ask again here on SO if you really can't find it) and turning it down, with luck that will "solve" your problem.

There's probably an underlying problem you should address, as the message isn't issued for the heck of it. But I don't understand generics well enough to fix it.

Something else that may be involved is the java compiler version. Check which compiler version level is set in Eclipse, and which one is called in Maven; they may well be different.

Carl Smotricz
  • 66,391
  • 18
  • 125
  • 167
  • I can't identify a compiler flag or setting that would disable this behaviour. I want the same compilation rules as my raw javac; where can I find the preference you've mentioned? All of my compiler compliance options seem to be on "warning" or "ignore" but I may have missed one. – Chris R Jul 17 '10 at 01:54
  • I would have liked to try to duplicate your problem, but I don't have access to most of the code dependencies. I'd recommend posting a small(er) self-contained example (not necessarily directly here; I'd use PasteBin) so folks can cut&paste and either experience the errors themselves, or not. – Carl Smotricz Jul 17 '10 at 07:49