1

in this Link, it is declared that we can not create an array of parameterzide type. Create an Array of Arraylists

but in java reflect, we can call getConstructors() method and save it's returned objects as below.

Constructor<?>[] constructors = MyClass.class.getConstructors();

so the question is, isn't it also a parameterized type object ?

Constructor<?>[]

if yes, then why does it work here ?

pail
  • 45
  • 4

2 Answers2

1

Good question. You can surely define an array of parameterized type bye breaking type safety like,

ArrayList<Individual> [] group = new ArrayList()[4] //unchecked warning

Arrays are covariant subtypes, which means Strings [] is a subtype of Object [] and are implemented in way that the elements we are adding is checked at runtime for there types like,

String [] stArr = new String[10]
Object [] objects = strings;
objects[0] = new Integer(); // Runtime ArrayStoreException will be thrown

To prevent wrong assignments, compiler does runtime checks of every array assignment.

while generics are compile time only. So Java would not be able to identify generic type once aliased to subtype, like,

ArrayList<Integer> [] lstArr = new ArrayList[10];
Object [] objArr= lstArr;
ArrayList<String> strList = new ArrayList<String>();        
objArr[0] = strList; // No runtime exception here

Unbounded wildcard type is only way as while putting the elements, no real type check is required for unbounded wildcard type.

ArrayList<?>[] lstArr = new ArrayList<?>[10];
lstArr[0] = new ArrayList<Integer>();

Hope this answers your question.

ihimanshu19
  • 136
  • 1
  • 8
1

First, declaring the return type as Constructor<?>[] does not imply creating an array of Constructor<?>, does it? It's just saying "this method returns this type". Just saying that does not create an array, so no errors there.

But getConstructors is going to create a Constructor<?>[] somewhere in its implementation, right? How does that work?

Well, after tracing the source code of getConstructors, I found this line where an array is created:

Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];

This line (creating an empty array) is executed if the Class is an interface. (If the Class is not an interface, then a native method gets called.) Why can a Constructor<?>[] be created?

The Oracle documentation in this case is not 100% accurate (this is not to say you should not trust it anymore), because Constructor<?> is a parameterised type, but new Constructor<?>[0] is valid.

Let's have a look at what a more authoritative document - the Java Language Specification - says about creating arrays of generic types:

15.10.1. Array Creation Expressions

[...]

It is a compile-time error if the ClassOrInterfaceType does not denote a reifiable type (§4.7). Otherwise, the ClassOrInterfaceType may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type.

A reifiable type is defined as:

4.7 Reifiable Types

A type is reifiable if and only if one of the following holds:

  • It refers to a non-generic class or interface type declaration.

  • It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).

  • [...]

The second bullet point applies to Constructor<?>. This is why you could create a new Constructor<?>[10].

Sweeper
  • 145,870
  • 17
  • 129
  • 225