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:
parent
3692e122ff
commit
cc0665cb6f
|
|
@ -3,36 +3,48 @@
|
||||||
|
|
||||||
package com.microsoft.signalr;
|
package com.microsoft.signalr;
|
||||||
|
|
||||||
|
import java.lang.ClassCastException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.ParameterizedType;
|
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;
|
private final Type type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of {@link TypeReference}.
|
* 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
|
* <pre>{@code
|
||||||
* Type fooType = (new TypeReference<Foo>() { }).getType();
|
* Type fooBarType = (new TypeReference<Foo<Bar>>() { }).getType();
|
||||||
* }</pre>
|
* }</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() {
|
public TypeReference() {
|
||||||
Type superclass = getClass().getGenericSuperclass();
|
try {
|
||||||
if (superclass instanceof Class) {
|
this.type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
||||||
throw new RuntimeException("Missing type parameter.");
|
} 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.
|
* Gets the referenced type.
|
||||||
* @return The Type encapsulated by this TypeReference
|
* @return The Type encapsulated by this TypeReference
|
||||||
*/
|
*/
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue