Generic type parameters don't feature at runtime. Check this:
List<Long> list = [1, 2, 3]
list.each{println it.getClass()}
Which prints:
class java.lang.Integer
class java.lang.Integer
class java.lang.Integer
The true confusion is introduced by the bizarre behavior difference between .equals
and ==
implementations:
Long.valueOf(3).equals(Integer.valueOf(3))
===> false
Long.valueOf(3) == Integer.valueOf(3)
===> true
List.contains
seems to be using .equals
, which checks the class of the parameter, thus explaining why forcing element types to Long
resolves the problem.
So, in the midst of this uncertainty, I think the only sure thing is that Groovy's ==
execution performs the most intuitive and predictable comparison. So I'd change the check to:
boolean contains = list.grep{it == 3L} //sets value to true if matches at least 1
It helps when one doesn't have to be cognizant of data types linked to literals:
def ints = [1, 2, 3]
def longs = [1L, 2L, 3L]
boolean found1 = ints.grep{it == 3L}
boolean found2 = ints.grep{it == 3}
boolean found3 = longs.grep{it == 3L}
boolean found4 = longs.grep{it == 3}
println found1
println found2
println found3
println found4
Which works as anyone would want:
true
true
true
true