Reputation: 705
I discovered in a production code a casting from List<List<Integer>>
to List<Integer>
which does not make any sense, but it's working without any problem being raised, so I wrote a quick test to check it out and to my surprise a List<List<Object>>
can behave like a List<Object>
static void main(String[] args) {
List<List<Integer>> list = []
list.add(1)
println(list.get(0))
println(list.get(0).getClass())
}
the output is:
1
class java.lang.Integer
I understand that we can define lists containing values of heterogeneous types like def heterogeneous = [1, "a", true]
, but in the example above the static typing clearly indicates that it should be List<List<Integer>>
Any explanation of the weird behavior ?
Upvotes: 2
Views: 482
Reputation: 20699
In straight-forward Groovy code, the type checking of Lists or other generic typed objects is weak.
Meaning that a List<List<Integer>>
can be fed with any objects, like Strings, integers or arrays.
To make the type checking real, you should use @CompileStatic
or @TypeChecked
annotations like so:
@groovy.transform.CompileStatic
def getInts(){
List<List<Integer>> ints = []
ints << 1
ints << [ '2' ]
ints << [ 3 ]
}
getInts()
The code above throws 2 compilation errors:
startup failed:
Script1.groovy: 4: [Static type checking] - Cannot call <T> java.util.List <List>#leftShift(T) with arguments [int]
@ line 4, column 3.
ints << 1
^
Script1.groovy: 5: [Static type checking] - Cannot call <T> java.util.List <List>#leftShift(T) with arguments [java.util.List <java.lang.String>]
@ line 5, column 3.
ints << [ '2' ]
^
2 errors
so that only the line ints << [ 3 ]
is valid.
Upvotes: 4