Reputation: 504
I've been playing around with Groovy and ran into this interesting thing. Checking whether a list of longs contains a particular number works when checking integer values, but not when checking long values.
List<Long> list = [5, 7, 3]
println (5 in list) // true
println (5L in list) // false
int i = 5
long l = 5
println (i in list) // true
println (l in list) // false
Integer i2 = 5
Long l2 = 5
println (i2 in list) // true
println (l2 in list) // false
I ran this code on https://groovyconsole.appspot.com/. This seems broken to me (or at least highly counter-intuitive). I'd expect there to be some issues within the implementation of List.contains and what comparison operator it is using? I can work around that, but I'm wondering if there is something that I'm missing or if that is actually intended behavior?
Upvotes: 4
Views: 1956
Reputation: 15368
The problem is that you initialize the list with integers. Simply initialize your list with long values:
List<Long> list = [5L, 7L, 3L]
Now you will get what you expect.
Upvotes: 0
Reputation: 8119
This is because type erasure, i.e., no type information at runtime. Since groovy is a dynamic language (dynamic dispatch for methods calls with Meta-Object Protocol, etc.), there is no type checking/static compilation by default.
So your groovy code is roughly equivalent to this groovy code:
def list = [5, 7, 3]
// no type checking by default, so generics types does not matter due to type erasure
[...]
or this pre-generics java code:
List list = new ArrayList();
list.add(5);
list.add(7);
list.add(3);
System.out.println(list.contains(5)); // true
System.out.println(list.contains(5L)); // false
[...]
If you compile that in java (better with -Xlint) you get the classic Unchecked Error Messages.
From groovy 2.0, you can turn on type checking/static compilation with @groovy.transform.TypeChecked
/ @groovy.transform.CompileStatic
(static compilation triggers also type checking):
@groovy.transform.CompileStatic
class Test {
static main(args) {
List<Long> list = [5, 7, 3]
println (5 in list) // true
println (5L in list) // false
int i = 5
long l = 5
println (i in list) // true
println (l in list) // false
Integer i2 = 5
Long l2 = new Long(5)
println (i2 in list) // true
println (l2 in list) // false
}
}
So that you get a compilation error:
[Static type checking] - Incompatible generic argument types. Cannot assign java.util.List <java.lang.Integer> to: java.util.List <Long>
Upvotes: 2