public class AbstractEntityFactory<E extends Entity> {
public Class getEntityClass() {
return E. class ;
}
}
ArrayList <Float> listOfNumbers = new ArrayList <Float>();
then, due to the erasure of types, we cannot analyze the listOfNumbers to find out that this is an ArrayList parameterized by Float, and not by anything else. Unfortunately, Java Generics work this way: (public class FloatList extends ArrayList <Float>{}
ArrayList <Float> listOfNumbers = new FloatList ();
Class actualClass = listOfNumbers.getClass();
ParameterizedType type = (ParameterizedType)actualClass.getGenericSuperclass();
System. out .println(type); // java.util.ArrayList<java.lang.Float>
Class parameter = (Class)type.getActualTypeArguments()[0];
System. out .println(parameter); // class java.lang.Float
public class ReflectionUtils {
public static Class getGenericParameterClass(Class actualClass, int parameterIndex) {
return (Class) ((ParameterizedType) actualClass.getGenericSuperclass()).getActualTypeArguments()[parameterIndex];
}
}
public class AbstractEntityFactory<E extends Entity> {
public Class getEntityClass() {
return ReflectionUtils.getGenericParameterClass( this .getClass(), 0);
}
}
public class ReflectionUtilsTest extends TestCase {
// ""
static class A<K, L> {
// String, Integer
}
static class B<P, Q, R extends Collection> extends A<Q, P> {
// Integer, String, Set
}
static class C<X extends Comparable< String >, Y, Z> extends B<Z, X, Set<Long>> {
// String, Double, Integer
}
static class D<M, N extends Comparable<Double>> extends C< String , N, M> {
// Integer, Double
}
static class E extends D<Integer, Double> {
//
}
}
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Stack;
/**
* Alex Tracer (c) 2009
*/
public class ReflectionUtils {
/**
* generic-.
*
* @param actualClass
* @param genericClass ,
* @param parameterIndex
* @return , parameterIndex genericClass
*/
public static Class getGenericParameterClass(final Class actualClass, final Class genericClass, final int parameterIndex) {
// genericClass actualClass.
if (!genericClass.isAssignableFrom(actualClass.getSuperclass())) {
throw new IllegalArgumentException( "Class " + genericClass.getName() + " is not a superclass of "
+ actualClass.getName() + "." );
}
// , genericClass.
// , .
// genericClasses - .
// - .
Stack<ParameterizedType> genericClasses = new Stack<ParameterizedType>();
// clazz -
Class clazz = actualClass;
while ( true ) {
Type genericSuperclass = clazz.getGenericSuperclass();
boolean isParameterizedType = genericSuperclass instanceof ParameterizedType;
if (isParameterizedType) {
// - , - .
genericClasses.push((ParameterizedType) genericSuperclass);
} else {
// . .
genericClasses.clear();
}
// , .
Type rawType = isParameterizedType ? ((ParameterizedType) genericSuperclass).getRawType() : genericSuperclass;
if (!rawType.equals(genericClass)) {
// genericClass .
// .
clazz = clazz.getSuperclass();
} else {
// . .
break ;
}
}
// . , .
Type result = genericClasses.pop().getActualTypeArguments()[parameterIndex];
while (result instanceof TypeVariable && !genericClasses.empty()) {
// - , .
// , .
int actualArgumentIndex = getParameterTypeDeclarationIndex((TypeVariable) result);
// , .
ParameterizedType type = genericClasses.pop();
// .
result = type.getActualTypeArguments()[actualArgumentIndex];
}
if (result instanceof TypeVariable) {
// , .
// - "Type erasure" .
throw new IllegalStateException( "Unable to resolve type variable " + result + "."
+ " Try to replace instances of parametrized class with its non-parameterized subtype." );
}
if (result instanceof ParameterizedType) {
// .
// , .
result = ((ParameterizedType) result).getRawType();
}
if (result == null ) {
// Should never happen. :)
throw new IllegalStateException( "Unable to determine actual parameter type for "
+ actualClass.getName() + "." );
}
if (!(result instanceof Class)) {
// , - - , .
throw new IllegalStateException( "Actual parameter type for " + actualClass.getName() + " is not a Class." );
}
return (Class) result;
}
public static int getParameterTypeDeclarationIndex(final TypeVariable typeVariable) {
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
// , .
TypeVariable[] typeVariables = genericDeclaration.getTypeParameters();
Integer actualArgumentIndex = null ;
for ( int i = 0; i < typeVariables.length; i++) {
if (typeVariables[i].equals(typeVariable)) {
actualArgumentIndex = i;
break ;
}
}
if (actualArgumentIndex != null ) {
return actualArgumentIndex;
} else {
throw new IllegalStateException( "Argument " + typeVariable.toString() + " is not found in "
+ genericDeclaration.toString() + "." );
}
}
}
public class AbstractEntityFactory<E extends Entity> {
public Class getEntityClass() {
return ReflectionUtils.getGenericParameterClass( this .getClass(), AbstractEntityFactory. class , 0);
}
}
public class Topic extends Entity {
}
public class TopicFactory extends AbstractEntityFactory<Topic> {
public void doSomething() {
Class entityClass = getEntityClass(); // Topic
}
}
Source: https://habr.com/ru/post/66593/
All Articles