How are references to << T >> handled by the compiler in the following code, since the method takes no parameters that would allow inference of T? Are any restrictions being placed on what type of object can be placed into the list? Is a cast even taking place on the line where I add the String to the list? My first thought is that without anything to infer T from, T becomes an Object type. Thanks in advance.
public class App {
private <T> void parameterizedMethod()
{
List<T> list = new ArrayList<>();
for(int i = 0; i < 10; i++)
{
list.add((T)new String()); //is a cast actually occurring here?
}
}
public App()
{
parameterizedMethod();
}
public static void main(String[] args) {
new App();
}
}
This is initially determined by 18.1.3:
At the end of inference, the bound set gets "resolved" to the inferred type. Without any additional context, the bound set will only consist of the initial bounds based on the declaration of the type parameter.
A bound with a form like
αl <: Object
meansαl
(an inference variable) isObject
or a subtype ofObject
. This bound is resolved toObject
.So in your case, yes,
Object
is inferred.If we declared a type bound:
then
SomeType
will be inferred.No cast actually happens in this case (erasure). That's why it's "unchecked". A cast only happens when the object is exposed due to e.g.:
Semantically (compile-time), yes. And note that the restriction is determined outside the method. Inside the method, we don't know what that restriction actually is. So we should not be putting
String
in aList<T>
. We don't know whatT
is.Practically (run-time), no. It's just a
List
and there's no checked cast.parameterizedMethod
won't cause an exception...but that only holds for this kind of isolated example. This kind of code may very well lead to issues.