Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关联Java字段类型和泛型参数_Java_Generics_Reflection - Fatal编程技术网

关联Java字段类型和泛型参数

关联Java字段类型和泛型参数,java,generics,reflection,Java,Generics,Reflection,考虑以下类别: class A { B<Integer> b; } class B<T> { T t; } 这样,当调用create(A.class)时,返回的值是A的实例,其中包含b.t中的整数。当然,除了类之外,方法不能有任何关于A的知识 众所周知,如何找出A中b的类型是b 我正在寻找一种方法,以确定B中的t字段打算具有B的第一个类型参数的类型。作为类型参数的字段类型可分配给java.lang.reflect.TypeVariable。换句话说,f

考虑以下类别:

class A {
    B<Integer> b;
}

class B<T> {
    T t;
}
这样,当调用
create(A.class)
时,返回的值是A的实例,其中包含
b.t
中的整数。当然,除了类之外,方法不能有任何关于
A
的知识

众所周知,如何找出
A
b
的类型是
b


我正在寻找一种方法,以确定
B
中的
t
字段打算具有
B
的第一个类型参数的类型。作为类型参数的字段类型可分配给
java.lang.reflect.TypeVariable
。换句话说,
field.getGenericType()
在为字段
B.t
调用时返回
TypeVariable
的实例

下面的完整示例适用于问题中给出的玩具箱。一般情况更为复杂,因为必须跟踪多个级别的类型参数

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

class Main {
    static class A {
        B<Integer> b;
    }

    static class B<T> {
        T t;
    }

    public static void main(String[] args) throws Exception {
        A a = (A)create(A.class);
        System.out.println(a.b.t.getClass());
        // prints java.lang.Integer
    }

    static Object create(Class<?> clazz) throws Exception {
        return create(clazz, new Type[0]);
    }

    static Object create(Class<?> clazz, Type[] typeArguments) throws Exception {
        Object object;
        if (clazz == Integer.class || clazz == int.class) {
            return 0;
        } else {
            object = clazz.newInstance();
        }
        for (Field field : object.getClass().getDeclaredFields()) {
            Type[] fieldTypeArguments = { };
            Type fieldType = field.getGenericType();
            if (fieldType instanceof TypeVariable) {
                TypeVariable<?> typeVariable = (TypeVariable<?>) fieldType;
                TypeVariable<?>[] typeParameters = typeVariable.getGenericDeclaration().getTypeParameters();
                for (int i = 0; i < typeParameters.length; i++) {
                    if (typeParameters[i] == typeVariable) {
                        fieldType = typeArguments[i];
                    }
                }
            } else if (fieldType instanceof ParameterizedType) {
                fieldTypeArguments = ((ParameterizedType) fieldType).getActualTypeArguments();
            }
            Class<?> fieldClass = null;
            if (fieldType instanceof Class) {
                fieldClass = (Class<?>) fieldType;
            } else if (fieldType instanceof ParameterizedType) {
                fieldClass = (Class<?>) ((ParameterizedType) fieldType).getRawType();
            }
            field.set(object, create(fieldClass, fieldTypeArguments));
        }
        return object;
    }
}
import java.lang.reflect.Field;
导入java.lang.reflect.ParameterizedType;
导入java.lang.reflect.Type;
导入java.lang.reflect.TypeVariable;
班长{
静态A类{
B B;
}
静态B类{
T;
}
公共静态void main(字符串[]args)引发异常{
A=(A)创建(A.class);
System.out.println(a.b.t.getClass());
//打印java.lang.Integer
}
静态对象创建(类clazz)引发异常{
返回创建(clazz,新类型[0]);
}
静态对象创建(类clazz,类型[]typeArguments)引发异常{
对象对象;
if(clazz==Integer.class | | clazz==int.class){
返回0;
}否则{
object=clazz.newInstance();
}
对于(字段:object.getClass().getDeclaredFields()){
类型[]fieldTypeArguments={};
Type fieldType=field.getGenericType();
if(fieldType instanceof TypeVariable){
类型变量类型变量=(类型变量)字段类型;
TypeVariable[]typeParameters=TypeVariable.getGenericDeclaration().getTypeParameters();
对于(int i=0;i
由于类型擦除,无法查看字段的类型。您所能做的最好的事情就是检查当前值的类型
Class bClass=/*whatever*/;如果(bClass.isInstance(t)){…}
Java没有删除所有泛型类型信息。很容易发现
A
B
的类型参数是
Integer
。因此,某些泛型类型信息必须存储在类文件中。我的问题是,是否可以使用此信息将类型参数与
B
B.t
的字段类型关联起来。Michael是正确的。但是,您还需要了解泛型用于增强编译时类型检查。它不能应用于从类对象创建对象,除了已经存在的对象(即类中的
T newInstance()
)@MuhKarma它不会删除所有类型信息,但在特定情况下会删除。“因此必须存储一些泛型类型信息”是的,完全正确。一些它在第一种情况下会这样做,而不是在第二种情况下。这种行为是定义良好的,以前在堆栈溢出和其他地方都已经讨论过很多次。只需谷歌“Java类型擦除”
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

class Main {
    static class A {
        B<Integer> b;
    }

    static class B<T> {
        T t;
    }

    public static void main(String[] args) throws Exception {
        A a = (A)create(A.class);
        System.out.println(a.b.t.getClass());
        // prints java.lang.Integer
    }

    static Object create(Class<?> clazz) throws Exception {
        return create(clazz, new Type[0]);
    }

    static Object create(Class<?> clazz, Type[] typeArguments) throws Exception {
        Object object;
        if (clazz == Integer.class || clazz == int.class) {
            return 0;
        } else {
            object = clazz.newInstance();
        }
        for (Field field : object.getClass().getDeclaredFields()) {
            Type[] fieldTypeArguments = { };
            Type fieldType = field.getGenericType();
            if (fieldType instanceof TypeVariable) {
                TypeVariable<?> typeVariable = (TypeVariable<?>) fieldType;
                TypeVariable<?>[] typeParameters = typeVariable.getGenericDeclaration().getTypeParameters();
                for (int i = 0; i < typeParameters.length; i++) {
                    if (typeParameters[i] == typeVariable) {
                        fieldType = typeArguments[i];
                    }
                }
            } else if (fieldType instanceof ParameterizedType) {
                fieldTypeArguments = ((ParameterizedType) fieldType).getActualTypeArguments();
            }
            Class<?> fieldClass = null;
            if (fieldType instanceof Class) {
                fieldClass = (Class<?>) fieldType;
            } else if (fieldType instanceof ParameterizedType) {
                fieldClass = (Class<?>) ((ParameterizedType) fieldType).getRawType();
            }
            field.set(object, create(fieldClass, fieldTypeArguments));
        }
        return object;
    }
}