Skip to content

Instantly share code, notes, and snippets.

@odrotbohm
Created November 15, 2016 15:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odrotbohm/c644327bb89191f2b52e298427ebf201 to your computer and use it in GitHub Desktop.
Save odrotbohm/c644327bb89191f2b52e298427ebf201 to your computer and use it in GitHub Desktop.
Compiler ambiguity when compiling with target JDK 8
public class AmbiguitySample {
/**
* This compiles when using a JDK 8 with target JDK 6 but fails when the target is JDK 8.
*/
public static void main(String[] args) {
CriteriaBuilder builder;
Expression<Object> objectExpression;
Expression<Collection<Object>> collectionOfObjectExpression;
// Compiler error: AmbiguitySample.java:[35,24] reference to isNotMember is ambiguous
// [ERROR] both method
// <E,C>isNotMember(javax.persistence.criteria.Expression<E>,javax.persistence.criteria.Expression<C>) in
// javax.persistence.criteria.CriteriaBuilder and method
// <E,C>isNotMember(E,javax.persistence.criteria.Expression<C>) in javax.persistence.criteria.CriteriaBuilder match
builder.isNotMember(objectExpression, collectionOfObjectExpression);
// ^^^^^^^^^^^
}
}
@nipafx
Copy link

nipafx commented Nov 15, 2016

Not that I have any chance of answering this but it would be easier to play around with if it contained all required source code.

@otrosien
Copy link

otrosien commented Nov 15, 2016

This problem kept me interested a while... It seems like a problem in "target-type inference" from java8. See: http://stackoverflow.com/questions/32294140/java-8-reference-to-method-is-ambiguous . Java8 is using target-type inference to infer the type of E, but there must be an exception when using <Object> as generic type, because if you use something different/more specific, it will work. Here is another working alternative:

    void test(CriteriaBuilder builder, 
            Expression<? extends Object> objectExpression, 
            Expression<? extends Collection<Object>> collectionOfObjectExpression) {
        builder.isNotMember(objectExpression, collectionOfObjectExpression);
    }

You can also trick the compiler into the correct behavior with this piece of code:

    <T> void test(CriteriaBuilder builder, Expression<T> objectExpression,
    Expression<Collection<T>> collectionOfObjectExpression) {
        builder.isNotMember(objectExpression, collectionOfObjectExpression);
    }

@odrotbohm
Copy link
Author

Sorry, I've been in a hurry and thought I'd just oversee something. I've no prepared a reproducing example here. Run mvn clean compile see it fail. Change the java.version property to 1.6 see it compile.

$ java -version
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode)

@odrotbohm
Copy link
Author

@otrosien — once again, you made my day. Thanks for that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment