Fields from type T - java

I want to get all the fields and it's values from an object of type T. Say I have:
public class Start {
public void startMethod(){
Main<GenericType> main = new Main<>();
main.work(new GenericType());
}
}
Then there's class Main, where I want the fields of GenericType:
public class Main<T> {
public void work(T t){
// Is there a way to get t's fields and values?
}
}

First,you need to get Class of T,then through reflection ,you can get all fields.
abstract class A<T> {
Class<T> clazz;
void doGetClass() {
Type genType = this.getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
this.clazz = (Class<T>) params[0];
}
}
but you must instantiate the generic type ,like this,instantiate T to String:
class B extends A<String>{
}
then
B b = new B();
b.doGetClass();// b.clazz is String.class

Following #BalwinderSingh's answer I came to this:
public void work(T t){
for(Field f : t.getClass().getDeclaredFields()){
try {
f.setAccessible(true);
String name = f.getName();
Object value = f.get(object);
}catch(Exception e){
e.printStackTrace();
}
}
}
It was simpler than I though at the beginning. Thank you all.

Related

Using a generic type of any nested subclass within its abstract superclass

Suppose you have the following abstract java class:
public abstract class AbstractRequestHandler<I,O> {
I input;
O output;
}
and the following child classes hierarchy:
public abstract class AbstractUserRequestHandler<I extends User,O> extends AbstractRequestHandler<I,O>{...}
public abstract class AbstractUniversityRequestHandler<I extends UniversityUser> extends AbstractUserRequestHandler<I,String>{...}
public class StudentRequestHandler extends AbstractUniversityRequestHandler<Student>{...}
public class TeacherRequestHandler extends AbstractUniversityRequestHandler<Teacher>{...}
Suppose you need to use at a given point on the super class the generic type, for example in order to deserialize on the constructor the request json to the specific request object using gson library as follow:
public AbstractRequestHandler(final String inputJson) {
input = new Gson().fromJson(inputJson,typeOfI);
}
You need the type of generic I within variable "typeOfI"
Is there a global solution that allows to get the generic type specified by a concrete child class that respects the following constraints?
The type is gotten at runtime regardless the child classes hierarchy ( that can be also more complex the one given as example on this question )
The developer just needs to define the generic extending the super class without manually specify the generic type somewhere on concrete child class ( for example on overrided method or constructor )
So that if you want to define a new concrete child that assign a new value to a generic you can just write the following concrete class for example:
public class StudentRequestHandler extends AbstractUniversityRequestHandler<Student>{
public StudentRequestHandler(String inputJson) {
super(inputJson);
}
}
I found the following solutions but they don't respect both the asked solution constraints.
Solution that breaks constraint n°2
A solution could be to define an abstract method on the superclass as follow
protected abstract Type getRequestType();
and then implement it on every concrete child class that defines the generic:
public class StudentRequestHandler extends AbstractUniversityRequestHandler<Student>{
public StudentRequestHandler(String inputJson) {
super(inputJson);
}
#Override
protected Type getRequestType() {
return Student.class;
}
}
Then the getRequestType() method can be used on constructor on the target superclass:
public AbstractRequestHandler(final String inputJson) {
request = new Gson().fromJson(inputJson,getRequestType());
}
But even if it works regardless the child classes hierarchy ( respect constraint n°1 ) the developer should manually implement an abstract method on each concrete child class.
Solution that breaks constraint n°1
If the hierarchy is simple having only a direct child that extend from the target superclass, as for example:
public class TeacherRequestHandler extends AbstractRequestHandler<Teacher,String>{...}
a working solution has been proposed by #naikus ( https://stackoverflow.com/users/306602/naikus ) on the following stackoverflow thread:
Using a generic type of a subclass within it's abstract superclass?
However this doesn't work if the concrete class is not a direct child of the superclass that defines the generics ( as the one proposed as example on this question ).
Edit: after reading your answer and testing many other possible cases I decided to edit your code and re-write it to support all other possible edge cases to include tracking of generics nested deeply inside other generic types.
Sadly to support all cases we need a lot more code than you provided, generics are very tricky, like consider class like this:
private class SomeClass<A, B, C, D, E, F> {}
private class SomeConfusingClass<A> extends SomeClass<List<Void>[], List<? extends A>[], List<? extends A[][][]>[][][], List<? extends String[]>[], Map<List<? extends A[]>, A[][]>[], A> {}
private class TestClass extends SomeConfusingClass<Void> {}
To even start doing this we need to have own implementation of java generic types to later be able to construct types like List<String>[] as there is no way to create such type dynamically with raw java API.
This is pretty popular way of handling generic in libraries like that, you can see similar thing in jackson library and many more.
So we need implementation of GenericArrayType, ParameterizedType and WildcardType:
private static class ResolvedGenericArrayType implements GenericArrayType {
private final Type genericComponentType;
ResolvedGenericArrayType(Type genericComponentType) {
this.genericComponentType = genericComponentType;
}
#Override
public Type getGenericComponentType() {
return genericComponentType;
}
public String toString() {
return getGenericComponentType().toString() + "[]";
}
#Override
public boolean equals(Object o) {
if (o instanceof GenericArrayType) {
GenericArrayType that = (GenericArrayType) o;
return Objects.equals(genericComponentType, that.getGenericComponentType());
} else
return false;
}
#Override
public int hashCode() {
return Objects.hashCode(genericComponentType);
}
}
private static class ResolvedParameterizedType implements ParameterizedType {
private final Type[] actualTypeArguments;
private final Class<?> rawType;
private final Type ownerType;
private ResolvedParameterizedType(Type rawType, Type[] actualTypeArguments, Type ownerType) {
this.actualTypeArguments = actualTypeArguments;
this.rawType = (Class<?>) rawType;
this.ownerType = (ownerType != null) ? ownerType : this.rawType.getDeclaringClass();
}
public Type[] getActualTypeArguments() {
return actualTypeArguments.clone();
}
public Class<?> getRawType() {
return rawType;
}
public Type getOwnerType() {
return ownerType;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof ParameterizedType)) {
return false;
}
ParameterizedType that = (ParameterizedType) o;
if (this == that)
return true;
Type thatOwner = that.getOwnerType();
Type thatRawType = that.getRawType();
return Objects.equals(ownerType, thatOwner) && Objects.equals(rawType, thatRawType) &&
Arrays.equals(actualTypeArguments, that.getActualTypeArguments());
}
#Override
public int hashCode() {
return Arrays.hashCode(actualTypeArguments) ^
Objects.hashCode(ownerType) ^
Objects.hashCode(rawType);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (ownerType != null) {
sb.append(ownerType.getTypeName());
sb.append("$");
if (ownerType instanceof ResolvedParameterizedType) {
sb.append(rawType.getName().replace(((ResolvedParameterizedType) ownerType).rawType.getName() + "$", ""));
} else
sb.append(rawType.getSimpleName());
} else
sb.append(rawType.getName());
if (actualTypeArguments != null) {
StringJoiner sj = new StringJoiner(", ", "<", ">");
sj.setEmptyValue("");
for (Type t : actualTypeArguments) {
sj.add(t.getTypeName());
}
sb.append(sj.toString());
}
return sb.toString();
}
}
private static class ResolvedWildcardType implements WildcardType {
private final Type[] upperBounds;
private final Type[] lowerBounds;
public ResolvedWildcardType(Type[] upperBounds, Type[] lowerBounds) {
this.upperBounds = upperBounds;
this.lowerBounds = lowerBounds;
}
public Type[] getUpperBounds() {
return upperBounds.clone();
}
public Type[] getLowerBounds() {
return lowerBounds.clone();
}
public String toString() {
Type[] lowerBounds = getLowerBounds();
Type[] bounds = lowerBounds;
StringBuilder sb = new StringBuilder();
if (lowerBounds.length > 0)
sb.append("? super ");
else {
Type[] upperBounds = getUpperBounds();
if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class)) {
bounds = upperBounds;
sb.append("? extends ");
} else
return "?";
}
StringJoiner sj = new StringJoiner(" & ");
for (Type bound : bounds) {
sj.add(bound.getTypeName());
}
sb.append(sj.toString());
return sb.toString();
}
#Override
public boolean equals(Object o) {
if (o instanceof WildcardType) {
WildcardType that = (WildcardType) o;
return Arrays.equals(this.getLowerBounds(), that.getLowerBounds()) && Arrays.equals(this.getUpperBounds(), that.getUpperBounds());
} else
return false;
}
#Override
public int hashCode() {
Type[] lowerBounds = getLowerBounds();
Type[] upperBounds = getUpperBounds();
return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds);
}
}
You can basically copy them from JDK and just do some cleanup.
Next utility we need is a function to validate at the end if we did everything right, like we don't want to return Map<List<? extends X>[]> where X is still not resolved TypeVariable:
private static boolean isDefined(Type type) {
if (type instanceof Class) {
return true;
}
if (type instanceof GenericArrayType) {
return isDefined(((GenericArrayType) type).getGenericComponentType());
}
if (type instanceof WildcardType) {
for (Type lowerBound : ((WildcardType) type).getLowerBounds()) {
if (!isDefined(lowerBound)) {
return false;
}
}
for (Type upperBound : ((WildcardType) type).getUpperBounds()) {
if (!isDefined(upperBound)) {
return false;
}
}
return true;
}
if (!(type instanceof ParameterizedType)) {
return false;
}
for (Type typeArgument : ((ParameterizedType) type).getActualTypeArguments()) {
if (!isDefined(typeArgument)) {
return false;
}
}
return true;
}
Simple recursive function will do this for us. We just check for every possible generic type and check if every member of it is also defined, and unless we will find some hidden TypeVariable we are fine.
Main function can stay the same as in your code, we only will edit that one check at the end to use our new function:
public static Type getParameterizedType(Class<?> klass, Class<?> rootClass, int paramTypeNumber) throws GenericsException {
int targetClassParametersNumber = rootClass.getTypeParameters().length;
if (targetClassParametersNumber == 0) {
throw new GenericsException(String.format("Target class [%s] has no parameters type", rootClass.getName()));
} else if (targetClassParametersNumber - 1 < paramTypeNumber)
throw new GenericsException(String.format("Target class [%s] has parameters type which index start from [0] to [%s]. You requested instead parameter with index [%s]", rootClass, paramTypeNumber - 1, targetClassParametersNumber));
Type type = analyzeParameterizedTypes(klass, klass, rootClass, paramTypeNumber, null);
if (!isDefined(type))
throw new GenericsException(String.format("Parameter [%s] with index [%d] defined on class [%s] has not been valued yet on child class [%s]", type, paramTypeNumber, rootClass.getName(), klass.getName()));
return type;
}
Now lets work on our main
public static Type analyzeParameterizedTypes(final Class<?> klass, final Class<?> targetClass, final Class<?> rootClass, final int paramTypeNumber, Map<Integer, Type> childClassTypes) throws GenericsException {
function, the begging stays the same, we collect all TypeVariable to simple map, keeping already collected information from previous loop on previous class.
Type superclassType = klass.getGenericSuperclass();
Map<TypeVariable<?>, Type> currentClassTypes = new HashMap<>();
int z = 0;
if (childClassTypes != null) {
for (TypeVariable<?> variable : klass.getTypeParameters()) {
currentClassTypes.put(variable, childClassTypes.get(z));
z++;
}
}
Then we have our loop collecting and refining our type arguments:
Map<Integer, Type> superClassesTypes = new HashMap<>();
if (superclassType instanceof ParameterizedType) {
int i = 0;
for (final Type argType : ((ParameterizedType) superclassType).getActualTypeArguments()) {
if (argType instanceof TypeVariable) {
superClassesTypes.put(i, currentClassTypes.containsKey(argType) ? currentClassTypes.get(argType) : argType);
} else {
superClassesTypes.put(i, refineType(klass, argType, currentClassTypesByName));
}
i++;
}
}
There 2 paths for each type argument, if its TypeVariable we just keep tracking it, and if its anything else we try to "refine" it from any possible references to TypeVariable. This is the most complicated process of this code, and this is why we needed all these classes above.
We start from this simple recursive dispatch method that handles all possible types:
private static Type refineType(Type type, Map<TypeVariable<?>, Type> typeVariablesMap) throws GenericsException {
if (type instanceof Class) {
return type;
}
if (type instanceof GenericArrayType) {
return refineArrayType((GenericArrayType) type, typeVariablesMap);
}
if (type instanceof ParameterizedType) {
return refineParameterizedType((ParameterizedType) type, typeVariablesMap);
}
if (type instanceof WildcardType) {
return refineWildcardType((WildcardType) type, typeVariablesMap);
}
if (type instanceof TypeVariable) {
return typeVariablesMap.get(type);
}
throw new GenericsException("Unsolvable generic type: " + type);
}
And small utility method to run it on array of types:
private static Type[] refineTypes(Type[] types, Map<TypeVariable<?>, Type> typeVariablesMap) throws GenericsException {
Type[] refinedTypes = new Type[types.length];
for (int i = 0; i < types.length; i++) {
refinedTypes[i] = refineType(types[i], typeVariablesMap);
}
return refinedTypes;
}
Each type goes to own function, or if its TypeVariable we just fetch resolved one from map. Note that this can return null, and I did not handle it here. This could be improved later. For classes we don't need to do anything so we can just return class itself.
For GenericArrayType we need to first find out how many dimension such array might have (this could be handled by recursion in our refine method too, but then its a bit harder to debug in my opinion):
private static int getArrayDimensions(GenericArrayType genericArrayType) {
int levels = 1;
GenericArrayType currentArrayLevel = genericArrayType;
while (currentArrayLevel.getGenericComponentType() instanceof GenericArrayType) {
currentArrayLevel = (GenericArrayType) currentArrayLevel.getGenericComponentType();
levels += 1;
}
return levels;
}
Then we want to extract that nested component type of array, so for List<A>[][][] we want just List<A>:
private static Type getArrayNestedComponentType(GenericArrayType genericArrayType) {
GenericArrayType currentArrayLevel = genericArrayType;
while (currentArrayLevel.getGenericComponentType() instanceof GenericArrayType) {
currentArrayLevel = (GenericArrayType) currentArrayLevel.getGenericComponentType();
}
return currentArrayLevel.getGenericComponentType();
}
And then we need to refine this type, so our List<A> will change to eg List<String>:
Type arrayComponentType = refineType(getArrayNestedComponentType(genericArrayType), typeVariablesMap);
And rebuild our generic structure using refined type, so our created List<String> will change back to List<String>[][][]:
private static Type buildArrayType(Type componentType, int levels) throws GenericsException {
if (componentType instanceof Class) {
return Array.newInstance(((Class<?>) componentType), new int[levels]).getClass();
} else if (componentType instanceof ParameterizedType) {
GenericArrayType genericArrayType = new ResolvedGenericArrayType(componentType);
for (int i = 1; i < levels; i++) {
genericArrayType = new ResolvedGenericArrayType(genericArrayType);
}
return genericArrayType;
} else {
throw new GenericsException("Array can't be of generic type");
}
}
And whole function looks like this:
private static Type refineArrayType( GenericArrayType genericArrayType, Map<TypeVariable<?>, Type> typeVariablesMap) throws GenericsException {
int levels = getArrayDimensions(genericArrayType);
Type arrayComponentType = refineType(getArrayNestedComponentType(genericArrayType), typeVariablesMap);
return buildArrayType(arrayComponentType, levels);
}
For ParameterizedType its much simpler, we just refine type arguments, and create new ParameterizedType instance with these refined arguments:
private static Type refineParameterizedType(ParameterizedType parameterizedType, Map<TypeVariable<?>, Type> typeVariablesMap) throws GenericsException {
Type[] refinedTypeArguments = refineTypes(parameterizedType.getActualTypeArguments(), typeVariablesMap);
return new ResolvedParameterizedType(parameterizedType.getRawType(), refinedTypeArguments, parameterizedType.getOwnerType());
}
Same for WildcardType:
private static Type refineWildcardType(WildcardType wildcardType, Map<TypeVariable<?>, Type> typeVariablesMap) throws GenericsException {
Type[] refinedUpperBounds = refineTypes(wildcardType.getUpperBounds(), typeVariablesMap);
Type[] refinedLowerBounds = refineTypes(wildcardType.getLowerBounds(), typeVariablesMap);
return new ResolvedWildcardType(refinedUpperBounds, refinedLowerBounds);
}
And this leaves us with whole analyze function looking like this:
public static Type analyzeParameterizedTypes(final Class<?> klass, final Class<?> targetClass, final Class<?> rootClass, final int paramTypeNumber, Map<Integer, Type> childClassTypes) throws GenericsException {
Type superclassType = klass.getGenericSuperclass();
Map<TypeVariable<?>, Type> currentClassTypes = new HashMap<>();
int z = 0;
if (childClassTypes != null) {
for (TypeVariable<?> variable : klass.getTypeParameters()) {
currentClassTypes.put(variable, childClassTypes.get(z));
z++;
}
}
Map<Integer, Type> superClassesTypes = new HashMap<>();
if (superclassType instanceof ParameterizedType) {
int i = 0;
for (final Type argType : ((ParameterizedType) superclassType).getActualTypeArguments()) {
if (argType instanceof TypeVariable) {
superClassesTypes.put(i, currentClassTypes.getOrDefault(argType, argType));
} else {
superClassesTypes.put(i, refineType(argType, currentClassTypes));
}
i++;
}
}
if (klass != rootClass) {
final Class<?> superClass = klass.getSuperclass();
if (superClass == null)
throw new GenericsException(String.format("Class [%s] not found on class parent hierarchy [%s]", rootClass, targetClass));
return analyzeParameterizedTypes(superClass, targetClass, rootClass, paramTypeNumber, superClassesTypes);
}
return childClassTypes.get(paramTypeNumber);
}
Example usage:
private class SomeClass<A, B, C, D, E, F> {}
private class SomeConfusingClass<A> extends SomeClass<List<Void>[], List<? extends A>[], List<? extends A[][][]>[][][], List<? extends String[]>[], Map<List<? extends A[]>, A[][]>[], A> {}
private class TestClass extends SomeConfusingClass<Void> {}
public static void main(String[] args) throws Exception {
System.out.println(GenericsUtils.getParameterizedType(TestClass.class, SomeClass.class, 0));
System.out.println(GenericsUtils.getParameterizedType(TestClass.class, SomeClass.class, 1));
System.out.println(GenericsUtils.getParameterizedType(TestClass.class, SomeClass.class, 2));
System.out.println(GenericsUtils.getParameterizedType(TestClass.class, SomeClass.class, 3));
System.out.println(GenericsUtils.getParameterizedType(TestClass.class, SomeClass.class, 4));
System.out.println(GenericsUtils.getParameterizedType(TestClass.class, SomeClass.class, 5));
}
And results:
java.util.List<java.lang.Void>[]
java.util.List<? extends java.lang.Void>[]
java.util.List<? extends java.lang.Void[][][]>[][][]
java.util.List<? extends java.lang.String[]>[]
java.util.Map<java.util.List<? extends java.lang.Void[]>, java.lang.Void[][]>[]
class java.lang.Void
Whole code with tests can be found here: https://gist.github.com/GotoFinal/33b9e282f270dbfe61907aa830c27587 or here: https://github.com/GotoFinal/generics-utils/tree/edge-cases-1
Based on OP original answer code, but with most of edge cases covered.
The answer is: Java does not support reified generics, see this feature request from 2004 with lots of duplicates. See also:
C# has reified generics, Java does not
Kotlin reified generics example
Java generics, type erasure and again Kotlin's reified generics
So unless you want to switch to Kotlin, there is simply nothing you can do because generic type information in Java is available to the compiler only, not during runtime (reified generics).
I am sorry if you do not like the answer, but still it is correct as of Java 13 in early 2020.
I think a working solution would be to extend the one proposed by #naikus. It only needs to go up in the hierarchy on the constructor.
import java.lang.reflect.ParameterizedType;
public abstract class AbstractRequestHandler<I,O> {
protected I input;
protected O output;
protected Class<I> inputClass;
protected Class<O> outputClass;
protected AbstractRequestHandler() {
Class<?> clazz = getClass();
while (!clazz.getSuperclass().equals(AbstractRequestHandler.class)) {
clazz = clazz.getSuperclass();
}
ParameterizedType genericSuperclass = (ParameterizedType) clazz.getGenericSuperclass();
this.inputClass = (Class<I>) genericSuperclass.getActualTypeArguments()[0];
this.outputClass = (Class<O>) genericSuperclass.getActualTypeArguments()[1];
}
}
I've worked to an utility library that offers a method that generally solve the question analyzing recursively all parent classes hierarchy to get a specific generic type.
It is available on my GitHub project: https://github.com/gregorycallea/generics-utils
UPDATE: Thanks to #GoToFinal user that with his great effort improved the project covering also several differents complex
generics case ( such as GenericArrayType, ParameterizedType and
WildcardType).
For all details about these improvements see his answer on this question.
This is the summarized scenario the method works on:
Suppose you have a parameterized root class with an undefined number of generics defined.
Example: Let's consider as root class the following "Base" class that defines 3 generics:
private class Base<I, E, F> {
I var1;
E var2;
F var3;
}
NOTE: To each generic is assigned an index starting from 0. So index mapping for this class is:
I = 0
E = 1
F = 2
Suppose this root class have a complex and multi-leveled hierarchy of child classes.
Example:
// Base<I,E,F>
// BaseA<G,H> extends Base<H,Boolean,G>
// BaseB<T> extends BaseA<T,String>
// BaseC<H> extends BaseB<H>
// BaseD extends BaseC<Integer>
// BaseE extends BaseD
// BaseF extends BaseE
// BaseG extends BaseF
// BaseH<H> extends BaseG<H,Double>
// BaseI<T> extends BaseF<T>
// BaseL<J> extends BaseI<J>
// BaseM extends BaseL<Float>
// BaseN extends BaseM
NOTE: Notice that walking the child hierarchy new parameterized classes are defined and also some classes are not parameterized at all
Then suppose you want to choose whatever class on root class child hierarchy and then get the exactly type of a specific generic defined on root class starting from this.
Example:
You want to know the type of E generic ( with index = 1 ) defined on Base class starting from child class BaseN.
To do this you can simply execute the GenericsUtils.getParameterizedType method as follow:
Type targetType = GenericsUtils.getParameterizedType(GenericChildClass.class, RootClass.class, genericRootClassIndex);
Example:
Type EType = GenericsUtils.getParameterizedType(BaseN.class, Base.class, 1);
I evaluated several cases for this example scenario with unit tests.
Take a look at:
https://github.com/gregorycallea/generics-utils/blob/master/src/test/java/com/github/gregorycallea/generics/GenericsUtilsTest.java
About the initial scenario exposed on my question instead we can use this method on AbstractRequestHandler constructor as follow:
public abstract class AbstractRequestHandler<I,O> {
I input;
O output;
public AbstractRequestHandler(String inputJson) throws GenericsException {
this.input = new Gson().fromJson(inputJson,GenericsUtils.getParameterizedType(getClass(), AbstractRequestHandler.class, 0));
}
}

Java: How to get the class type of generics at runtime? [duplicate]

How can I achieve this?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Everything I have tried so far always returns type Object rather than the specific type used.
As others mentioned, it's only possible via reflection in certain circumstances.
If you really need the type, this is the usual (type-safe) workaround pattern:
public class GenericClass<T> {
private final Class<T> type;
public GenericClass(Class<T> type) {
this.type = type;
}
public Class<T> getMyType() {
return this.type;
}
}
I have seen something like this
private Class<T> persistentClass;
public Constructor() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
in the hibernate GenericDataAccessObjects Example
Generics are not reified at run-time. This means the information is not present at run-time.
Adding generics to Java while mantaining backward compatibility was a tour-de-force (you can see the seminal paper about it: Making the future safe for the past: adding genericity to the Java programming language).
There is a rich literature on the subject, and some people are dissatisfied with the current state, some says that actually it's a lure and there is no real need for it. You can read both links, I found them quite interesting.
Use Guava.
import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;
public abstract class GenericClass<T> {
private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) { };
private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>
public Type getType() {
return type;
}
public static void main(String[] args) {
GenericClass<String> example = new GenericClass<String>() { };
System.out.println(example.getType()); // => class java.lang.String
}
}
A while back, I posted some full-fledge examples including abstract classes and subclasses here.
Note: this requires that you instantiate a subclass of GenericClass so it can bind the type parameter correctly. Otherwise it'll just return the type as T.
Java generics are mostly compile time, this means that the type information is lost at runtime.
class GenericCls<T>
{
T t;
}
will be compiled to something like
class GenericCls
{
Object o;
}
To get the type information at runtime you have to add it as an argument of the ctor.
class GenericCls<T>
{
private Class<T> type;
public GenericCls(Class<T> cls)
{
type= cls;
}
Class<T> getType(){return type;}
}
Example:
GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;
Sure, you can.
Java does not use the information at run time, for backwards compatibility reasons. But the information is actually present as metadata and can be accessed via reflection (but it is still not used for type-checking).
From the official API:
http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29
However, for your scenario I would not use reflection. I'm personally more inclined to use that for framework code. In your case I would just add the type as a constructor param.
public abstract class AbstractDao<T>
{
private final Class<T> persistentClass;
public AbstractDao()
{
this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
}
I used follow approach:
public class A<T> {
protected Class<T> clazz;
public A() {
this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public Class<T> getClazz() {
return clazz;
}
}
public class B extends A<C> {
/* ... */
public void anything() {
// here I may use getClazz();
}
}
I dont think you can, Java uses type erasure when compiling so your code is compatible with applications and libraries that were created pre-generics.
From the Oracle Docs:
Type Erasure
Generics were introduced to the Java language to provide tighter type
checks at compile time and to support generic programming. To
implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or
Object if the type parameters are unbounded. The produced bytecode,
therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety. Generate
bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized
types; consequently, generics incur no runtime overhead.
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Technique described in this article by Ian Robertson works for me.
In short quick and dirty example:
public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
{
/**
* Method returns class implementing EntityInterface which was used in class
* extending AbstractDAO
*
* #return Class<T extends EntityInterface>
*/
public Class<T> returnedClass()
{
return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
}
/**
* Get the underlying class for a type, or null if the type is a variable
* type.
*
* #param type the type
* #return the underlying class
*/
public static Class<?> getClass(Type type)
{
if (type instanceof Class) {
return (Class) type;
} else if (type instanceof ParameterizedType) {
return getClass(((ParameterizedType) type).getRawType());
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class<?> componentClass = getClass(componentType);
if (componentClass != null) {
return Array.newInstance(componentClass, 0).getClass();
} else {
return null;
}
} else {
return null;
}
}
/**
* Get the actual type arguments a child class has used to extend a generic
* base class.
*
* #param baseClass the base class
* #param childClass the child class
* #return a list of the raw classes for the actual type arguments.
*/
public static <T> List<Class<?>> getTypeArguments(
Class<T> baseClass, Class<? extends T> childClass)
{
Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
Type type = childClass;
// start walking up the inheritance hierarchy until we hit baseClass
while (!getClass(type).equals(baseClass)) {
if (type instanceof Class) {
// there is no useful information for us in raw types, so just keep going.
type = ((Class) type).getGenericSuperclass();
} else {
ParameterizedType parameterizedType = (ParameterizedType) type;
Class<?> rawType = (Class) parameterizedType.getRawType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < actualTypeArguments.length; i++) {
resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
}
if (!rawType.equals(baseClass)) {
type = rawType.getGenericSuperclass();
}
}
}
// finally, for each actual type argument provided to baseClass, determine (if possible)
// the raw class for that type argument.
Type[] actualTypeArguments;
if (type instanceof Class) {
actualTypeArguments = ((Class) type).getTypeParameters();
} else {
actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
}
List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
// resolve types by chasing down type variables.
for (Type baseType : actualTypeArguments) {
while (resolvedTypes.containsKey(baseType)) {
baseType = resolvedTypes.get(baseType);
}
typeArgumentsAsClasses.add(getClass(baseType));
}
return typeArgumentsAsClasses;
}
}
I think there is another elegant solution.
What you want to do is (safely) "pass" the type of the generic type parameter up from the concerete class to the superclass.
If you allow yourself to think of the class type as "metadata" on the class, that suggests the Java method for encoding metadata in at runtime: annotations.
First define a custom annotation along these lines:
import java.lang.annotation.*;
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface EntityAnnotation {
Class entityClass();
}
You can then have to add the annotation to your subclass.
#EntityAnnotation(entityClass = PassedGenericType.class)
public class Subclass<PassedGenericType> {...}
Then you can use this code to get the class type in your base class:
import org.springframework.core.annotation.AnnotationUtils;
.
.
.
private Class getGenericParameterType() {
final Class aClass = this.getClass();
EntityAnnotation ne =
AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);
return ne.entityClass();
}
Some limitations of this approach are:
You specify the generic type (PassedGenericType) in TWO places rather than one which is non-DRY.
This is only possible if you can modify the concrete subclasses.
Here's one way, which I've had to use once or twice:
public abstract class GenericClass<T>{
public abstract Class<T> getMyType();
}
Along with
public class SpecificClass extends GenericClass<String>{
#Override
public Class<String> getMyType(){
return String.class;
}
}
This is my solution:
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
public class GenericClass<T extends String> {
public static void main(String[] args) {
for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
System.out.println(typeParam.getName());
for (Type bound : typeParam.getBounds()) {
System.out.println(bound);
}
}
}
}
Here is working solution!!!
#SuppressWarnings("unchecked")
private Class<T> getGenericTypeClass() {
    try {
        String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
        Class<?> clazz = Class.forName(className);
        return (Class<T>) clazz;
    } catch (Exception e) {
        throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
    }
}
NOTES:
Can be used only as superclass
1. Has to be extended with typed class (Child extends Generic<Integer>)
OR
2. Has to be created as anonymous implementation (new Generic<Integer>() {};)
You can't. If you add a member variable of type T to the class (you don't even have to initialise it), you could use that to recover the type.
One simple solution for this cab be like below
public class GenericDemo<T>{
private T type;
GenericDemo(T t)
{
this.type = t;
}
public String getType()
{
return this.type.getClass().getName();
}
public static void main(String[] args)
{
GenericDemo<Integer> obj = new GenericDemo<Integer>(5);
System.out.println("Type: "+ obj.getType());
}
}
To complete some of the answers here, I had to get the ParametrizedType of MyGenericClass, no matter how high is the hierarchy, with the help of recursion:
private Class<T> getGenericTypeClass() {
return (Class<T>) (getParametrizedType(getClass())).getActualTypeArguments()[0];
}
private static ParameterizedType getParametrizedType(Class clazz){
if(clazz.getSuperclass().equals(MyGenericClass.class)){ // check that we are at the top of the hierarchy
return (ParameterizedType) clazz.getGenericSuperclass();
} else {
return getParametrizedType(clazz.getSuperclass());
}
}
Here is my solution
public class GenericClass<T>
{
private Class<T> realType;
public GenericClass() {
findTypeArguments(getClass());
}
private void findTypeArguments(Type t) {
if (t instanceof ParameterizedType) {
Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments();
realType = (Class<T>) typeArgs[0];
} else {
Class c = (Class) t;
findTypeArguments(c.getGenericSuperclass());
}
}
public Type getMyType()
{
// How do I return the type of T? (your question)
return realType;
}
}
No matter how many level does your class hierarchy has,
this solution still works, for example:
public class FirstLevelChild<T> extends GenericClass<T> {
}
public class SecondLevelChild extends FirstLevelChild<String> {
}
In this case, getMyType() = java.lang.String
Here is my trick:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Main.<String> getClazz());
}
static <T> Class getClazz(T... param) {
return param.getClass().getComponentType();
}
}
Just in case you use store a variable using the generic type you can easily solve this problem adding a getClassType method as follows:
public class Constant<T> {
private T value;
#SuppressWarnings("unchecked")
public Class<T> getClassType () {
return ((Class<T>) value.getClass());
}
}
I use the provided class object later to check if it is an instance of a given class, as follows:
Constant<?> constant = ...;
if (constant.getClassType().equals(Integer.class)) {
Constant<Integer> integerConstant = (Constant<Integer>)constant;
Integer value = integerConstant.getValue();
// ...
}
Here is my solution. The examples should explain it. The only requirement is that a subclass must set the generic type, not an object.
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
public class TypeUtils {
/*** EXAMPLES ***/
public static class Class1<A, B, C> {
public A someA;
public B someB;
public C someC;
public Class<?> getAType() {
return getTypeParameterType(this.getClass(), Class1.class, 0);
}
public Class<?> getCType() {
return getTypeParameterType(this.getClass(), Class1.class, 2);
}
}
public static class Class2<D, A, B, E, C> extends Class1<A, B, C> {
public B someB;
public D someD;
public E someE;
}
public static class Class3<E, C> extends Class2<String, Integer, Double, E, C> {
public E someE;
}
public static class Class4 extends Class3<Boolean, Long> {
}
public static void test() throws NoSuchFieldException {
Class4 class4 = new Class4();
Class<?> typeA = class4.getAType(); // typeA = Integer
Class<?> typeC = class4.getCType(); // typeC = Long
Field fieldSomeA = class4.getClass().getField("someA");
Class<?> typeSomeA = TypeUtils.getFieldType(class4.getClass(), fieldSomeA); // typeSomeA = Integer
Field fieldSomeE = class4.getClass().getField("someE");
Class<?> typeSomeE = TypeUtils.getFieldType(class4.getClass(), fieldSomeE); // typeSomeE = Boolean
}
/*** UTILS ***/
public static Class<?> getTypeVariableType(Class<?> subClass, TypeVariable<?> typeVariable) {
Map<TypeVariable<?>, Type> subMap = new HashMap<>();
Class<?> superClass;
while ((superClass = subClass.getSuperclass()) != null) {
Map<TypeVariable<?>, Type> superMap = new HashMap<>();
Type superGeneric = subClass.getGenericSuperclass();
if (superGeneric instanceof ParameterizedType) {
TypeVariable<?>[] typeParams = superClass.getTypeParameters();
Type[] actualTypeArgs = ((ParameterizedType) superGeneric).getActualTypeArguments();
for (int i = 0; i < typeParams.length; i++) {
Type actualType = actualTypeArgs[i];
if (actualType instanceof TypeVariable) {
actualType = subMap.get(actualType);
}
if (typeVariable == typeParams[i]) return (Class<?>) actualType;
superMap.put(typeParams[i], actualType);
}
}
subClass = superClass;
subMap = superMap;
}
return null;
}
public static Class<?> getTypeParameterType(Class<?> subClass, Class<?> superClass, int typeParameterIndex) {
return TypeUtils.getTypeVariableType(subClass, superClass.getTypeParameters()[typeParameterIndex]);
}
public static Class<?> getFieldType(Class<?> clazz, AccessibleObject element) {
Class<?> type = null;
Type genericType = null;
if (element instanceof Field) {
type = ((Field) element).getType();
genericType = ((Field) element).getGenericType();
} else if (element instanceof Method) {
type = ((Method) element).getReturnType();
genericType = ((Method) element).getGenericReturnType();
}
if (genericType instanceof TypeVariable) {
Class<?> typeVariableType = TypeUtils.getTypeVariableType(clazz, (TypeVariable) genericType);
if (typeVariableType != null) {
type = typeVariableType;
}
}
return type;
}
}
If you have a class like:
public class GenericClass<T> {
private T data;
}
with T variable, then you can print T name:
System.out.println(data.getClass().getSimpleName()); // "String", "Integer", etc.
Use an abstract method that returns the class type then use it in that class and wherever you extend generic class you will have to implement that abstract method to return the required class type
public class AbsractService<T>{
public abstract Class<T> getClassType ();
.......
}
at runtime
class AnimalService extends AbstractService<Animal>{
#Override
public Class<Animal> getClassType (){
return Animal.class;
}
.....
}
public static final Class<?> getGenericArgument(final Class<?> clazz)
{
return (Class<?>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
}
If you are working with spring:
public static Class<?>[] resolveTypeArguments(Class<?> parentClass, Class<?> subClass) {
if (subClass.isSynthetic()) {
return null;
}
return GenericTypeResolver.resolveTypeArguments(subClass, parentClass);
}
By the way, GenericTypeResolver will still get null for the non-subclasses class like the question mentioned, because the generic info of such class was completely erased after compilation.
The only way to solve this question may be:
public class GenericClass<T>
{
private final Class<T> clazz;
public Foo(Class<T> clazz) {
this.clazz= clazz;
}
public Type getMyType()
{
return clazz;
}
}
If you cannot change the generic class and use one of the method already explained on this page, then simple approach would be to get the type class based on the runtime instance class name.
Class getType(GenericType runtimeClassMember){
if (ClassA.class.equals(runtimeClassMember.getClass()){
return TypeForClassA.class;
} else if (ClassB.class.equals(runtimeClassMember.getClass()){
return TypeForClassB.class;
}
//throw an expectation or do whatever you want for the cases not described in the if section.
}
I did the same as #Moesio Above but in Kotlin it could be done this way:
class A<T : SomeClass>() {
var someClassType : T
init(){
this.someClassType = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
}
}
This was inspired by Pablo's and CoolMind's answers.
Occasionally I have also used the technique from kayz1's answer (expressed in many other answers as well), and I believe it is a decent and reliable way to do what the OP asked.
I chose to define this as an interface (similar to PJWeisberg) first because I have existing types that would benefit from this functionality, particularly a heterogeneous generic union type:
public interface IGenericType<T>
{
Class<T> getGenericTypeParameterType();
}
Where my simple implementation in a generic anonymous interface implementation looks like the following:
//Passed into the generic value generator function: toStore
//This value name is a field in the enclosing class.
//IUnionTypeValue<T> is a generic interface that extends IGenericType<T>
value = new IUnionTypeValue<T>() {
...
private T storedValue = toStore;
...
#SuppressWarnings("unchecked")
#Override
public Class<T> getGenericTypeParameterType()
{
return (Class<T>) storedValue.getClass();
}
}
I imagine this could be also implemented by being built with a class definition object as the source, that's just a separate use-case.
I think the key is as many other answers have stated, in one way or another, you need to get the type information at runtime to have it available at runtime; the objects themselves maintain their type, but erasure (also as others have said, with appropriate references) causes any enclosing/container types to lose that type information.
It might be useful to someone. You can Use java.lang.ref.WeakReference;
this way:
class SomeClass<N>{
WeakReference<N> variableToGetTypeFrom;
N getType(){
return variableToGetTypeFrom.get();
}
}
I found this to be a simple understandable and easily explainable solution
public class GenericClass<T> {
private Class classForT(T...t) {
return t.getClass().getComponentType();
}
public static void main(String[] args) {
GenericClass<String> g = new GenericClass<String>();
System.out.println(g.classForT());
System.out.println(String.class);
}
}

Get generic type information [duplicate]

How can I achieve this?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Everything I have tried so far always returns type Object rather than the specific type used.
As others mentioned, it's only possible via reflection in certain circumstances.
If you really need the type, this is the usual (type-safe) workaround pattern:
public class GenericClass<T> {
private final Class<T> type;
public GenericClass(Class<T> type) {
this.type = type;
}
public Class<T> getMyType() {
return this.type;
}
}
I have seen something like this
private Class<T> persistentClass;
public Constructor() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
in the hibernate GenericDataAccessObjects Example
Generics are not reified at run-time. This means the information is not present at run-time.
Adding generics to Java while mantaining backward compatibility was a tour-de-force (you can see the seminal paper about it: Making the future safe for the past: adding genericity to the Java programming language).
There is a rich literature on the subject, and some people are dissatisfied with the current state, some says that actually it's a lure and there is no real need for it. You can read both links, I found them quite interesting.
Use Guava.
import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;
public abstract class GenericClass<T> {
private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) { };
private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>
public Type getType() {
return type;
}
public static void main(String[] args) {
GenericClass<String> example = new GenericClass<String>() { };
System.out.println(example.getType()); // => class java.lang.String
}
}
A while back, I posted some full-fledge examples including abstract classes and subclasses here.
Note: this requires that you instantiate a subclass of GenericClass so it can bind the type parameter correctly. Otherwise it'll just return the type as T.
Java generics are mostly compile time, this means that the type information is lost at runtime.
class GenericCls<T>
{
T t;
}
will be compiled to something like
class GenericCls
{
Object o;
}
To get the type information at runtime you have to add it as an argument of the ctor.
class GenericCls<T>
{
private Class<T> type;
public GenericCls(Class<T> cls)
{
type= cls;
}
Class<T> getType(){return type;}
}
Example:
GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;
Sure, you can.
Java does not use the information at run time, for backwards compatibility reasons. But the information is actually present as metadata and can be accessed via reflection (but it is still not used for type-checking).
From the official API:
http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29
However, for your scenario I would not use reflection. I'm personally more inclined to use that for framework code. In your case I would just add the type as a constructor param.
public abstract class AbstractDao<T>
{
private final Class<T> persistentClass;
public AbstractDao()
{
this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
}
I used follow approach:
public class A<T> {
protected Class<T> clazz;
public A() {
this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public Class<T> getClazz() {
return clazz;
}
}
public class B extends A<C> {
/* ... */
public void anything() {
// here I may use getClazz();
}
}
I dont think you can, Java uses type erasure when compiling so your code is compatible with applications and libraries that were created pre-generics.
From the Oracle Docs:
Type Erasure
Generics were introduced to the Java language to provide tighter type
checks at compile time and to support generic programming. To
implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or
Object if the type parameters are unbounded. The produced bytecode,
therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety. Generate
bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized
types; consequently, generics incur no runtime overhead.
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Technique described in this article by Ian Robertson works for me.
In short quick and dirty example:
public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
{
/**
* Method returns class implementing EntityInterface which was used in class
* extending AbstractDAO
*
* #return Class<T extends EntityInterface>
*/
public Class<T> returnedClass()
{
return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
}
/**
* Get the underlying class for a type, or null if the type is a variable
* type.
*
* #param type the type
* #return the underlying class
*/
public static Class<?> getClass(Type type)
{
if (type instanceof Class) {
return (Class) type;
} else if (type instanceof ParameterizedType) {
return getClass(((ParameterizedType) type).getRawType());
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class<?> componentClass = getClass(componentType);
if (componentClass != null) {
return Array.newInstance(componentClass, 0).getClass();
} else {
return null;
}
} else {
return null;
}
}
/**
* Get the actual type arguments a child class has used to extend a generic
* base class.
*
* #param baseClass the base class
* #param childClass the child class
* #return a list of the raw classes for the actual type arguments.
*/
public static <T> List<Class<?>> getTypeArguments(
Class<T> baseClass, Class<? extends T> childClass)
{
Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
Type type = childClass;
// start walking up the inheritance hierarchy until we hit baseClass
while (!getClass(type).equals(baseClass)) {
if (type instanceof Class) {
// there is no useful information for us in raw types, so just keep going.
type = ((Class) type).getGenericSuperclass();
} else {
ParameterizedType parameterizedType = (ParameterizedType) type;
Class<?> rawType = (Class) parameterizedType.getRawType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < actualTypeArguments.length; i++) {
resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
}
if (!rawType.equals(baseClass)) {
type = rawType.getGenericSuperclass();
}
}
}
// finally, for each actual type argument provided to baseClass, determine (if possible)
// the raw class for that type argument.
Type[] actualTypeArguments;
if (type instanceof Class) {
actualTypeArguments = ((Class) type).getTypeParameters();
} else {
actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
}
List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
// resolve types by chasing down type variables.
for (Type baseType : actualTypeArguments) {
while (resolvedTypes.containsKey(baseType)) {
baseType = resolvedTypes.get(baseType);
}
typeArgumentsAsClasses.add(getClass(baseType));
}
return typeArgumentsAsClasses;
}
}
I think there is another elegant solution.
What you want to do is (safely) "pass" the type of the generic type parameter up from the concerete class to the superclass.
If you allow yourself to think of the class type as "metadata" on the class, that suggests the Java method for encoding metadata in at runtime: annotations.
First define a custom annotation along these lines:
import java.lang.annotation.*;
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface EntityAnnotation {
Class entityClass();
}
You can then have to add the annotation to your subclass.
#EntityAnnotation(entityClass = PassedGenericType.class)
public class Subclass<PassedGenericType> {...}
Then you can use this code to get the class type in your base class:
import org.springframework.core.annotation.AnnotationUtils;
.
.
.
private Class getGenericParameterType() {
final Class aClass = this.getClass();
EntityAnnotation ne =
AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);
return ne.entityClass();
}
Some limitations of this approach are:
You specify the generic type (PassedGenericType) in TWO places rather than one which is non-DRY.
This is only possible if you can modify the concrete subclasses.
Here's one way, which I've had to use once or twice:
public abstract class GenericClass<T>{
public abstract Class<T> getMyType();
}
Along with
public class SpecificClass extends GenericClass<String>{
#Override
public Class<String> getMyType(){
return String.class;
}
}
This is my solution:
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
public class GenericClass<T extends String> {
public static void main(String[] args) {
for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
System.out.println(typeParam.getName());
for (Type bound : typeParam.getBounds()) {
System.out.println(bound);
}
}
}
}
Here is working solution!!!
#SuppressWarnings("unchecked")
private Class<T> getGenericTypeClass() {
    try {
        String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
        Class<?> clazz = Class.forName(className);
        return (Class<T>) clazz;
    } catch (Exception e) {
        throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
    }
}
NOTES:
Can be used only as superclass
1. Has to be extended with typed class (Child extends Generic<Integer>)
OR
2. Has to be created as anonymous implementation (new Generic<Integer>() {};)
You can't. If you add a member variable of type T to the class (you don't even have to initialise it), you could use that to recover the type.
One simple solution for this cab be like below
public class GenericDemo<T>{
private T type;
GenericDemo(T t)
{
this.type = t;
}
public String getType()
{
return this.type.getClass().getName();
}
public static void main(String[] args)
{
GenericDemo<Integer> obj = new GenericDemo<Integer>(5);
System.out.println("Type: "+ obj.getType());
}
}
To complete some of the answers here, I had to get the ParametrizedType of MyGenericClass, no matter how high is the hierarchy, with the help of recursion:
private Class<T> getGenericTypeClass() {
return (Class<T>) (getParametrizedType(getClass())).getActualTypeArguments()[0];
}
private static ParameterizedType getParametrizedType(Class clazz){
if(clazz.getSuperclass().equals(MyGenericClass.class)){ // check that we are at the top of the hierarchy
return (ParameterizedType) clazz.getGenericSuperclass();
} else {
return getParametrizedType(clazz.getSuperclass());
}
}
Here is my solution
public class GenericClass<T>
{
private Class<T> realType;
public GenericClass() {
findTypeArguments(getClass());
}
private void findTypeArguments(Type t) {
if (t instanceof ParameterizedType) {
Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments();
realType = (Class<T>) typeArgs[0];
} else {
Class c = (Class) t;
findTypeArguments(c.getGenericSuperclass());
}
}
public Type getMyType()
{
// How do I return the type of T? (your question)
return realType;
}
}
No matter how many level does your class hierarchy has,
this solution still works, for example:
public class FirstLevelChild<T> extends GenericClass<T> {
}
public class SecondLevelChild extends FirstLevelChild<String> {
}
In this case, getMyType() = java.lang.String
Here is my trick:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Main.<String> getClazz());
}
static <T> Class getClazz(T... param) {
return param.getClass().getComponentType();
}
}
Just in case you use store a variable using the generic type you can easily solve this problem adding a getClassType method as follows:
public class Constant<T> {
private T value;
#SuppressWarnings("unchecked")
public Class<T> getClassType () {
return ((Class<T>) value.getClass());
}
}
I use the provided class object later to check if it is an instance of a given class, as follows:
Constant<?> constant = ...;
if (constant.getClassType().equals(Integer.class)) {
Constant<Integer> integerConstant = (Constant<Integer>)constant;
Integer value = integerConstant.getValue();
// ...
}
Here is my solution. The examples should explain it. The only requirement is that a subclass must set the generic type, not an object.
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
public class TypeUtils {
/*** EXAMPLES ***/
public static class Class1<A, B, C> {
public A someA;
public B someB;
public C someC;
public Class<?> getAType() {
return getTypeParameterType(this.getClass(), Class1.class, 0);
}
public Class<?> getCType() {
return getTypeParameterType(this.getClass(), Class1.class, 2);
}
}
public static class Class2<D, A, B, E, C> extends Class1<A, B, C> {
public B someB;
public D someD;
public E someE;
}
public static class Class3<E, C> extends Class2<String, Integer, Double, E, C> {
public E someE;
}
public static class Class4 extends Class3<Boolean, Long> {
}
public static void test() throws NoSuchFieldException {
Class4 class4 = new Class4();
Class<?> typeA = class4.getAType(); // typeA = Integer
Class<?> typeC = class4.getCType(); // typeC = Long
Field fieldSomeA = class4.getClass().getField("someA");
Class<?> typeSomeA = TypeUtils.getFieldType(class4.getClass(), fieldSomeA); // typeSomeA = Integer
Field fieldSomeE = class4.getClass().getField("someE");
Class<?> typeSomeE = TypeUtils.getFieldType(class4.getClass(), fieldSomeE); // typeSomeE = Boolean
}
/*** UTILS ***/
public static Class<?> getTypeVariableType(Class<?> subClass, TypeVariable<?> typeVariable) {
Map<TypeVariable<?>, Type> subMap = new HashMap<>();
Class<?> superClass;
while ((superClass = subClass.getSuperclass()) != null) {
Map<TypeVariable<?>, Type> superMap = new HashMap<>();
Type superGeneric = subClass.getGenericSuperclass();
if (superGeneric instanceof ParameterizedType) {
TypeVariable<?>[] typeParams = superClass.getTypeParameters();
Type[] actualTypeArgs = ((ParameterizedType) superGeneric).getActualTypeArguments();
for (int i = 0; i < typeParams.length; i++) {
Type actualType = actualTypeArgs[i];
if (actualType instanceof TypeVariable) {
actualType = subMap.get(actualType);
}
if (typeVariable == typeParams[i]) return (Class<?>) actualType;
superMap.put(typeParams[i], actualType);
}
}
subClass = superClass;
subMap = superMap;
}
return null;
}
public static Class<?> getTypeParameterType(Class<?> subClass, Class<?> superClass, int typeParameterIndex) {
return TypeUtils.getTypeVariableType(subClass, superClass.getTypeParameters()[typeParameterIndex]);
}
public static Class<?> getFieldType(Class<?> clazz, AccessibleObject element) {
Class<?> type = null;
Type genericType = null;
if (element instanceof Field) {
type = ((Field) element).getType();
genericType = ((Field) element).getGenericType();
} else if (element instanceof Method) {
type = ((Method) element).getReturnType();
genericType = ((Method) element).getGenericReturnType();
}
if (genericType instanceof TypeVariable) {
Class<?> typeVariableType = TypeUtils.getTypeVariableType(clazz, (TypeVariable) genericType);
if (typeVariableType != null) {
type = typeVariableType;
}
}
return type;
}
}
If you have a class like:
public class GenericClass<T> {
private T data;
}
with T variable, then you can print T name:
System.out.println(data.getClass().getSimpleName()); // "String", "Integer", etc.
Use an abstract method that returns the class type then use it in that class and wherever you extend generic class you will have to implement that abstract method to return the required class type
public class AbsractService<T>{
public abstract Class<T> getClassType ();
.......
}
at runtime
class AnimalService extends AbstractService<Animal>{
#Override
public Class<Animal> getClassType (){
return Animal.class;
}
.....
}
public static final Class<?> getGenericArgument(final Class<?> clazz)
{
return (Class<?>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
}
If you are working with spring:
public static Class<?>[] resolveTypeArguments(Class<?> parentClass, Class<?> subClass) {
if (subClass.isSynthetic()) {
return null;
}
return GenericTypeResolver.resolveTypeArguments(subClass, parentClass);
}
By the way, GenericTypeResolver will still get null for the non-subclasses class like the question mentioned, because the generic info of such class was completely erased after compilation.
The only way to solve this question may be:
public class GenericClass<T>
{
private final Class<T> clazz;
public Foo(Class<T> clazz) {
this.clazz= clazz;
}
public Type getMyType()
{
return clazz;
}
}
If you cannot change the generic class and use one of the method already explained on this page, then simple approach would be to get the type class based on the runtime instance class name.
Class getType(GenericType runtimeClassMember){
if (ClassA.class.equals(runtimeClassMember.getClass()){
return TypeForClassA.class;
} else if (ClassB.class.equals(runtimeClassMember.getClass()){
return TypeForClassB.class;
}
//throw an expectation or do whatever you want for the cases not described in the if section.
}
I did the same as #Moesio Above but in Kotlin it could be done this way:
class A<T : SomeClass>() {
var someClassType : T
init(){
this.someClassType = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
}
}
This was inspired by Pablo's and CoolMind's answers.
Occasionally I have also used the technique from kayz1's answer (expressed in many other answers as well), and I believe it is a decent and reliable way to do what the OP asked.
I chose to define this as an interface (similar to PJWeisberg) first because I have existing types that would benefit from this functionality, particularly a heterogeneous generic union type:
public interface IGenericType<T>
{
Class<T> getGenericTypeParameterType();
}
Where my simple implementation in a generic anonymous interface implementation looks like the following:
//Passed into the generic value generator function: toStore
//This value name is a field in the enclosing class.
//IUnionTypeValue<T> is a generic interface that extends IGenericType<T>
value = new IUnionTypeValue<T>() {
...
private T storedValue = toStore;
...
#SuppressWarnings("unchecked")
#Override
public Class<T> getGenericTypeParameterType()
{
return (Class<T>) storedValue.getClass();
}
}
I imagine this could be also implemented by being built with a class definition object as the source, that's just a separate use-case.
I think the key is as many other answers have stated, in one way or another, you need to get the type information at runtime to have it available at runtime; the objects themselves maintain their type, but erasure (also as others have said, with appropriate references) causes any enclosing/container types to lose that type information.
It might be useful to someone. You can Use java.lang.ref.WeakReference;
this way:
class SomeClass<N>{
WeakReference<N> variableToGetTypeFrom;
N getType(){
return variableToGetTypeFrom.get();
}
}
I found this to be a simple understandable and easily explainable solution
public class GenericClass<T> {
private Class classForT(T...t) {
return t.getClass().getComponentType();
}
public static void main(String[] args) {
GenericClass<String> g = new GenericClass<String>();
System.out.println(g.classForT());
System.out.println(String.class);
}
}

'X.class' to get it's 'X' type?

I have written simple container that registers a class and it's interface and has a method to create object from that information like this:
public class DIContainer {
protected static DIContainer instance;
protected Hashtable<Class<?>, Class<?>> classMap;
protected DIContainer(){
this.classMap = new Hashtable<Class<?>, Class<?>>();
}
public static DIContainer getInstance(){
if (DIContainer.instance == null)
DIContainer.instance = new DIContainer();
return DIContainer.instance;
}
public void regClass(Class<?> interf, Class<?> classToReg){
this.classMap.put(interf, classToReg);
}
public Object create(Class<?> interf) throws Exception{
if(!this.classMap.containsKey(interf))
throw new Exception("No such class registered with "+interf.getName()+" interface");
return this.classMap.get(interf).newInstance();
}
}
But I want before creating new instance to bypass it to proxy, for it to create, so I have this proxy class:
public class MyProxy implements InvocationHandler
{
private Map map;
private Object obj;
public static Object newInstance(Map map, Object obj, Class[] interfaces)
{
return Proxy.newProxyInstance(map.getClass().getClassLoader(),
interfaces,
new MyProxy(map, obj));
}
public MyProxy(Map map, Object obj)
{
this.map = map;
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws
Throwable
{
try {
return m.invoke(obj, args);
} catch (NoSuchMethodError e)
{
//Object result;
String methodName = m.getName();
if (methodName.startsWith("get"))
{
String name = methodName.substring(methodName.indexOf("get")+3);
return map.get(name);
}
else if (methodName.startsWith("set"))
{
String name = methodName.substring(methodName.indexOf("set")+3);
map.put(name, args[0]);
return null;
}
else if (methodName.startsWith("is"))
{
String name = methodName.substring(methodName.indexOf("is")+2);
return(map.get(name));
}
return null;
}
}
}
But for proxy class I need to provide type of class and it's interface, but I only have it's information with X.class. Can get the type (for example if it's class X) X, when I have X.class? Maybe I'm doing this the wrong way and I need to change something in order for it to work, but right now I figured I need to get that class type, so then I could provide it for proxy?
Because if I would right something like this:
X.class x;
I would get error. So I need to write like this X x;, but I only have X.class
Update:
To explain it simply, is it possible to get this:
X obj;
when you only have X.class (with X.class.newInstance it would instantiate it (like with new?), but I need not instantiated obj yet).
Update2
I tried this:
Object x = (Object) MyProxy.newInstance(map, this.classMap.get(interf).newInstance(), new Class[] {this.classMap.get(interf)});
But then I get this error:
Exception in thread "main" java.lang.IllegalArgumentException: class lab.X is not visible from class loader
My class X looks like this:
public class X implements I{
String name;
X(){}
#Override
public String getName() {
return name;
}
#Override
public void setName(String name) {
this.name = name;
}
}
and it's interface looks like this:
public interface I {
public String getName();
public void setName(String name);
}
If I understand correctly, you are trying to instantiate an element of the class X.class? If that is the case, all you need to do is call X.class.newInstance().
java.lang.IllegalArgumentException: class lab.X is not visible from
class loader
Isn't this error message quite clear? You need to make sure that the same class loader is being used.
In here:
public static Object newInstance(Map map, Object obj, Class[] interfaces)
{
return Proxy.newProxyInstance(map.getClass().getClassLoader(),
interfaces,
new MyProxy(map, obj));
}
you shouldn't be using the class loader of the map, I'd think you should use class loader of the target object or pass the proper class loader as a separate argument.
I think there are other problems in your approach as well, such as not synchronizing your container creation and not using generics for your proxy type.
For the first part, class DIContainer, it would be better to use:
protected final Map<Class<?>, Class<?>> classMap;
protected DIContainer() {
classMap = Collections.synchronizedMap(new HashMap<Class<?>, Class<?>>());
}
public <I> void regClass(Class<I> interf, Class<? extends I> classToReg) {
this.classMap.put(interf, classToReg);
}
public <T> T create(Class<T> interf) throws Exception {
Class<?> implClass = classMap.get(interf);
if (implClass == null) {
throw new Exception("No such class registered with " + interf.getName()
+ " interface");
}
Constructor<?> c = implClass.getConstructor();
c.setAccessible(true); // If default constructor not public
return interf.cast(c.newInstance());
}
Safe typing, though still partly at run-time.
More or less obsolete Hashtable replaced by equivalent
Calling newInstance on the class bypasses exceptions thrown on getting the default constructor and doing that one's newInstance.
The second part of the question: I fail to understand it; the interface class(es) is what is proxied. In the create above you could easily proxy Class<T> and yield a (seemingly) T object. And you could delegate in the proxy class to an T object created as in the create above.

Getting sub class fields using super class using reflection?

I have a class as below.
public class Emp{
private String name;
private String age;
//setters and getters
}
Have one more class below.
public class Student extends Emp{
private int marks;
//setters and getters
}
is there anyway to get the fields of a subclass using super class using java Reflection?
I need to get Student fields using Emp instance.
we can get super class fields as below:
subClass.getClass().getSuperclass().getDeclaredFields();
similarly can i get sub class fields using super class?
Is it possible?
Thanks!
I may have misunderstood your question. Do you want to do something like the following?
Emp e = new Student(...);
[do something with e]
foo = e.marks;
If yes, do it like this:
foo = ((Emp)e).marks;
However, if you want to do something like the following:
Emp e = new Emp(...);
[do something with e]
e.marks = ....
Then no, it's not possible, and I'd suspect your internal model of java's object model is either incomplete or flawed.
In theory there is a very complicated and costly way by retrieving all loaded classes and checking which of them are derived from Emp and contain the field. If the desired class wasn't loaded yet this may not help either.
Not directly, you have to write a helper method to that.
You take a class and the field name (and possibly type) as parameters, then look for that field in the given class. If you cant find it, you take the class's superclass and repeat from the beginning. You do this until you either found the field, or getSuperClass() returned null (meaning you reached the root of the inheritance tree).
This example demonstrates how to call find and call a specified method on an object. You can easily extract and adapt the logic for fields.
public static Object call(final Object instance,
final String methodName,
final Class<?>[] signature,
final Object[] args) {
try {
if (instance == null)
return null;
Class<?> instanceClass = instance.getClass();
while (instanceClass != null) {
try {
final Method method = instanceClass.getDeclaredMethod(methodName, signature);
if (!method.isAccessible())
method.setAccessible(true);
return method.invoke(instance, args);
} catch (final NoSuchMethodException e) {
// ignore
}
instanceClass = instanceClass.getSuperclass();
}
} catch (final Throwable e) {
return null;
}
return null;
}
Is it what you want? But beware of using field.setAccesible.
Parent class:
public class ParentClass {
private String parentField = "parentFieldValue";
public void printFields() throws IllegalAccessException {
Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object fieldValue = field.get(this);
if (fieldValue instanceof String) {
String stringValue = (String) fieldValue;
System.out.println(stringValue);
}
}
}
}
Child class:
public class ChildClass extends ParentClass {
private String childField = "childFieldValue";
}
Usage:
public class Main {
public static void main(String[] args) throws IllegalAccessException {
ParentClass pc = new ParentClass();
ChildClass cc = new ChildClass();
pc.printFields();
cc.printFields();
}
}
This is the final solution!
#NonNull
public static List<Class<?>> getSubClasses() {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
String method = trace[3].getMethodName();
if (!"<init>".equals(method)) {
throw new IllegalStateException("You can only call this method from constructor!");
}
List<Class<?>> subClasses = new ArrayList<>();
for (int i = 4; i < trace.length; i++) {
method = trace[i].getMethodName();
if ("<init>".equals(method)) {
try {
subClasses.add(Class.forName(trace[i].getClassName()));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
return subClasses;
}
this are some examples of usage:
class a {
public a(){
print(getSubClasses());
}
}
class b extends a{
}
class c extends b{
}
And the result is
new a() -> []
new b() -> [b.class]
new c() -> [b.class, c.class]

Categories

Resources