You are seeing the result of Type Erasure. From that page...
When a generic type is instantiated,
the compiler translates those types by
a technique called type erasure — a
process where the compiler removes all
information related to type parameters
and type arguments within a class or
method. Type erasure enables Java
applications that use generics to
maintain binary compatibility with
Java libraries and applications that
were created before generics.
For instance, Box<String> is
translated to type Box, which is
called the raw type — a raw type is a
generic class or interface name
without any type arguments. This means
that you can't find out what type of
Object a generic class is using at
runtime.
I'm not 100% sure if this works in all cases (needs at least Java 1.5):
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class Main
{
public class A
{
}
public class B extends A
{
}
public Map<A, B> map = new HashMap<Main.A, Main.B>();
public static void main(String[] args)
{
try
{
Field field = Main.class.getField("map");
System.out.println("Field " + field.getName() + " is of type " + field.getType().getSimpleName());
Type genericType = field.getGenericType();
if(genericType instanceof ParameterizedType)
{
ParameterizedType type = (ParameterizedType) genericType;
Type[] typeArguments = type.getActualTypeArguments();
for(Type typeArgument : typeArguments)
{
Class<?> classType = ((Class<?>)typeArgument);
System.out.println("Field " + field.getName() + " has a parameterized type of " + classType.getSimpleName());
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
This will output:
Field map is of type Map
Field map has a parameterized type of A
Field map has a parameterized type of B