Reputation: 1538
In the following code, my intuition is that the variables x and y get the same type:
var x = field(select(T.A).from(T));
var y = select(T.A).from(T).asField();
If I ask IntelliJ to replace var
with explicit type I get:
Field<String> x = field(select(T.A).from(T));
Field<Object> y = select(T.A).from(T).asField();
I trust IntelliJ over my intuition, so now I wonder why. Is this a limitation in Java? A bug in jOOQ? Something else?
Here's the method signatures for field
and asField
for reference:
public static <T> Field<T> field(Select<? extends Record1<T>> select);
public <T> Field<T> asField();
Upvotes: 1
Views: 28
Reputation: 1
To ensure y has the correct type (Field), you can explicitly specify the type parameter for asField():
Field<String> y = select(T.A).from(T).<String>asField();
Upvotes: 0
Reputation: 220867
DSL.field()
is a generic method that can capture its type variable T
. FieldLike.asField()
cannot capture a type variable based on whatever subtype of FieldLike
you're using, including Select<R>
. Due to a historic mistake, it's still a generic record, which allows you to unsafely cast the T
type at the use-site. But that's just an unsafe cast, not a correct capture of your desired type String
There's no way the asField()
method could be fixed in Java as the jOOQ API is designed right now, because the type variable R
in Select<R>
is not aware of the fact whether it is effectively a Record1<T>
(a scalar subquery), or anything else.
Other languages can add additional "constraints" on their generic type bounds, or they allow for using extension methods to give the feeling of a .asField()
"method", which in fact is really just a static
function like DSL.field()
, but with a suffix notation on their first parameter.
The only valid solution in Java would have been ot "overload" the Select
type with:
Select1<T1, R extends Record1<T1>> extends Select<R>
Select2<T1, T2, R extends Record2<T1, T2>> extends Select<R>
Select3<T1, T2, T3, R extends Record3<T1, T2, T3>> extends Select<R>
But that would have tons of additional, undesirable side effects thoughout the jOOQ API, which is why the idea was rejected and DSL.field()
was introduced.
Logically, the two methods are equivalent, but DSL.field()
is superior because it captures the correct type.
Upvotes: 1