Reflection and Generics Core Java

The Class class is now generic. For example, String.class is actually an object (in fact, thesole object) of the class Class<String>.

The type parameter is useful because it allows the methods of Class<T> to be more specificabout their return types. The following methods of Class<T> take advantage of thetype parameter:

The newInstance method returns an instance of the class, obtained from the default constructor.

Its return type can now be declared to be T, the same type as the class that isbeing described by Class<T>. That saves a cast. The cast method returns the given object, now declared as type T if its type is indeed asubtype of T. Otherwise, it throws a BadCastException. The getEnumConstants method returns null if this class is not an enum class or an array of theenumeration values, which are known to be of type T. Finally, the getConstructor and getDeclared Constructor methods return a Constructor<T> object.

The Constructor class has also been made generic so that its newInstance method has thecorrect return type.

java.lang.Class<T>1.0

  • T newInstance() 5.0

returns a new instance constructed with the default constructor.

  • T cast(Object obj) 5.0

returnsobj if it is null or can be converted to the type T, or throws a BadCastExceptionotherwise.

  • T[] getEnumConstants() 5.0

returns an array of all values if T is an enumerated type, null otherwise.

  • Class<? super T>getSuperclass() 5.0

returns the superclass of this class, or null if T is not a class or the class Object.

  • Constructor<T>getConstructor(Class... parameterTypes) 5.0
  • Constructor<T>getDeclaredConstructor(Class... parameterTypes) 5.0

gets the public constructor, or the constructor with the given parameter types.

java.lang.reflect.Constructor<T>1.1

  • T newInstance(Object... parameters) 5.0

returns a new instance constructed with the given parameters.

Using Class<T>Parameters for Type Matching

It is sometimes useful to match the type variable of a Class<T> parameter in a genericmethod. Here is the canonical example:

thenEmployee.class is an object of type Class<Employee>. The type parameter T of the makePairmethod matches Employee, and the compiler can infer that the method returns a Pair<Employee>.

Generic Type Information in the Virtual Machine

One of the notable features of Java generics is the erasure of generic types in the virtualmachine. Perhaps surprisingly, the erased classes still retain some faint memory of theirgeneric origin. For example, the raw Pair class knows that it originated from the genericclass Pair<T>, even though an object of type Pair can’t tell whether it was constructed as a Pair<String> or Pair<Employee>.

Similarly, consider a method

You can use the reflection API enhancements of Java SE 5.0 to determine that

  • The generic method has a type parameter called T;
  • The type parameter has a subtype bound that is itself a generic type;
  • The bounding type has a wildcard parameter;
  • The wildcard parameter has a supertype bound; and
  • The generic method has a generic array parameter.

In other words, you get to reconstruct everything about generic classes and methodsthat their implementors declared. However, you won’t know how the type parameterswere resolved for specific objects or method calls. The type information that is contained in class files to enable reflection of generics is incompatible with older virtual machines.

In order to express generic type declarations, Java SE 5.0 introduced a new interface Typein the java.lang.reflect package. The interface has the following subtypes:

  • The Class class, describing concrete types
  • The TypeVariable interface, describing type variables (such as T extends Comparable<?super T>)
  • The WildcardType interface, describing wildcards (such as ? super T)
  • The ParameterizedType interface, describing generic class or interface types (such asComparable<? super T>)
  • The GenericArrayType interface, describing generic arrays (such as T[])

Below it shows the inheritance hierarchy. Note that the last four subtypes are interfaces—the virtual machine instantiates suitable classes that implement these interfaces.

The Type class and its descendant

The Type class and its descendant

Listing below uses the generic reflection API to print out what it discovers about a givenclass. If you run it with the Pair class, you get this report:

If you run it with ArrayAlg in the PairTest2 directory, the report displays the followingmethod:

java.lang.Class<T>1.0

  • TypeVariable[] getTypeParameters() 5.0

    gets the generic type variables if this type was declared as a generic type, or an array of length 0 otherwise.

  • Type getGenericSuperclass() 5.0

    gets the generic type of the superclass that was declared for this type, or null if thistype is Object or not a class type.

  • Type[] getGenericInterfaces() 5.0

    gets the generic types of the interfaces that were declared for this type, in declaration order, or an array of length 0 if this type doesn’t implement interfaces.

java.lang.reflect.Method1.1

  • TypeVariable[] getTypeParameters() 5.0

    gets the generic type variables if this method was declared as a generic method, oran array of length 0 otherwise.

  • Type getGenericReturnType() 5.0

    gets the generic return type with which this method was declared.

  • Type[] getGenericParameterTypes() 5.0

    gets the generic parameter types with which this method was declared. If the method has no parameters, an array of length 0 is returned.

java.lang.reflect.TypeVariable5.0

  • String getName()

gets the name of this type variable.

  • Type[] getBounds()

gets the subclass bounds of this type variable, or an array of length 0 if thevariable is unbounded.

java.lang.reflect.WildcardType5.0

  • Type[] getLowerBounds()

gets the subclass (extends) bounds of this type variable, or an array of length 0 has no subclass bounds

  • Type[] getUpperBounds()

gets the superclass (super) bounds of this type variable, or an array of length 0 hasno superclass bounds.

  • Type getRawType()gets the raw type of this parameterized type.

java.lang.reflect.ParameterizedType5.0

  • Type[] getActualTypeArguments()

gets the type parameters with which this parameterized type was declared.

  • Type getOwnerType()

gets the outer class type if this is an inner type, or null if this is a top-level type.

java.lang.reflect.GenericArrayType

  • Type getGenericComponentType()

gets the generic component type with which this array type was declared. You now know how to use generic classes and how to program your own genericclasses and methods if the need arises. Just as importantly, you know how to decipher the generic type declarations that you may encounter in the API documentation and in error messages.



Face Book Twitter Google Plus Instagram Youtube Linkedin Myspace Pinterest Soundcloud Wikipedia

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Core Java Topics