Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
464 views
in Technique[技术] by (71.8m points)

generics - Why is anonymous class required in "super type token" pattern in java

In Neal Gafter's "super type token" pattern (http://gafter.blogspot.com/2006/12/super-type-tokens.html), an anonymous object was used to pass in the parameterized type :

class ReferenceType<T>{}

/* anonymous subclass of "ReferenceType" */
ReferenceType<List<Integer>> referenceType = new ReferenceType<List<Integer>>(){

};
Type superClass = b.getClass().getGenericSuperclass();
System.out.println("super type : " + superClass);
Type genericType = ((ParameterizedType)superClass).getActualTypeArguments()[0];
System.out.println("actual parameterized type : " + genericType);

Then result is :

super type : com.superluli.test.ReferenceType<java.util.List<java.lang.Integer>>
actual parameterized type : java.util.List<java.lang.Integer>

My question is, what the magic does the anonymous object "referenceType" do to make it work? If I define a explicit subclass of "ReferenceType" and use it instead of the anonymous style, it doesn't as expected.

class ReferenceType<T>{}
class ReferenceTypeSub<T> extends ReferenceType<T>{}

/* explicitly(or, named) defined subclass of "ReferenceType" */
ReferenceType<List<Integer>> b = new ReferenceTypeSub<List<Integer>>();
Type superClass = b.getClass().getGenericSuperclass();
System.out.println("super type : " + superClass);
Type genericType = ((ParameterizedType)superClass).getActualTypeArguments()[0];
System.out.println("actual parameterized type : " + genericType);

The result is :

super type : com.superluli.test.ReferenceType<T>
actual parameterized type : T
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This

ReferenceType<List<Integer>> referenceType = new ReferenceType<List<Integer>>(){

is equivalent to

public class AnonymousReferenceType extends ReferenceType<List<Integer>> {}
...
ReferenceType<List<Integer>> referenceType = new AnonymousReferenceType();

The hack works around Class#getGenericSuperclass() which states

Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class. If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code. The parameterized type representing the superclass is created if it had not been created before. See the declaration of ParameterizedType for the semantics of the creation process for parameterized types. If this Class represents either the Object class, an interface, a primitive type, or void, then null is returned. If this object represents an array class then the Class object representing the Object class is returned.

In other words, the superclass of AnonymousReferenceType is a ParameterizedType representing ReferenceType<List<Integer>>. This ParameterizedType has an actual type argument and that is a List<Integer> which is what appears in the source code.


In your second example, which is not the same as your first,

class ReferenceType<T>{}
class ReferenceTypeSub<T> extends ReferenceType<T>{}

the super class (super type) of ReferenceTypeSub is a ReferenceType<T> which is a ParameterizedType where the actual type argument is a TypeVariable named T, which is what appears in the source code.


To answer your question, you don't need an anonymous class. You just need a sub class which declares the type argument you want to use.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...