Search code examples
javagenericsjavacjooqoverloading

Ambiguous method call not resolved by casting


I am trying to do something like:

t.set(field("ColumnName"), select(max(field("ColumnName"))).from("TableName"));

But I am getting the following compile error:

    Ambiguous method call, Both
    set(Field,Object)                    in InsertSetStep and
    set(Field,Select<? extends Record1>) in InsertSetStep match

I have tried to resolve the ambiguity with casting, but I still receive the same error

Select<? extends Record1> sq = select(max(field("ColumnName"))).from("TableName");
t.set( field("ColumnName"), (Select<? extends Record1>)sq );

I have a couple questions:

  1. Why does casting not resolve the ambiguity in this scenario? (I have tried casting to (Object) and that does resolve the ambiguity)
  2. Is there a way for me to resolve the ambiguity?

Solution

  • This is a very unfortunate, but specified behaviour of the Java language and the various compilers. While pre-generics, the method taking a Select type is going to be more specific for your particular call, it is no longer so, once generics are involved. The rationale can be seen here.

    There's not much a heavily generic and overloaded API like jOOQ can do, but you can, as a user. You have to avoid binding <T> to Object in such cases, either by using the code generator, or by passing data types manually:

    // Assuming this is an INTEGER type
    t.set(
        field("ColumnName", SQLDataType.INTEGER), 
        select(max(field("ColumnName", SQLDataType.INTEGER))).from("TableName"));
    

    Or, you start storing your column references in some static variables like:

    Field<Integer> COLUMN_NAME = field("ColumnName", SQLDataType.INTEGER);
    
    // And then:
    t.set(COLUMN_NAME, select(max(COLUMN_NAME)).from("TableName"));
    

    Using the code generator

    Note, this is hardly ever a problem when you're using the code generator, in case of which you have specific type information bound to the <T> types of your Field<T> references, in case of which the overloads won't both be applicable anymore.

    I really recommend you use the code generator for this reason (and for many others).