TypeReference usage clarification (#25719)

This change makes TypeReference usage a little bit easier

- Marking it abstract make it so that usages cannot "forget" subclassing (or omitting the { } part). Previously the error message would be confusing as the supertype would be Object.
- Removing the instanceof check and relying on exception since instantiating TypeReference without a type parameter (new TypeReference() ) *is* exceptional as it goes against the intention of this class altogether.
- Added some clarification to the javadoc regarding intended usage, and a link to prior art for further reading.
This commit is contained in:
Ken Egozi 2020-09-10 15:02:21 -07:00 committed by GitHub
parent 3692e122ff
commit cc0665cb6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 21 additions and 9 deletions

View File

@ -3,36 +3,48 @@
package com.microsoft.signalr;
import java.lang.ClassCastException;
import java.lang.reflect.Type;
import java.lang.reflect.ParameterizedType;
/**
* A utility for getting a Java Type from a literal Class.
* A utility for getting a Java Type from a literal generic Class.
*/
public class TypeReference<T> {
public abstract class TypeReference<T> {
private final Type type;
/**
* Creates a new instance of {@link TypeReference}.
*
* To get the Type of Class Foo, use the following syntax:
* This class implements Super Type Tokens (Gafter's Gadget) as a way to get a reference to generic types in
* spite of type erasure since, sadly, {@code Foo<Bar>.class} is not valid Java.
*
* To get the Type of Class {@code Foo<Bar>}, use the following syntax:
* <pre>{@code
* Type fooType = (new TypeReference<Foo>() { }).getType();
* Type fooBarType = (new TypeReference<Foo<Bar>>() { }).getType();
* }</pre>
*
* To get the Type of class Foo, use a regular Type Token:
* <pre>{@code
* Type fooType = Foo.class;
* }</pre>
*
* @see <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html">Super Type Tokens</a>
*/
public TypeReference() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
try {
this.type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
} catch (ClassCastException ex) {
throw new RuntimeException("TypeReference must be instantiated with a type parameter such as (new TypeReference<Foo<Bar>>() {}).");
}
this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
}
/**
* Gets the referenced type.
* @return The Type encapsulated by this TypeReference
*/
*/
public Type getType() {
return this.type;
}