java - 关于泛型和反射的代码错误(cannot select from a type variable)
迷茫
迷茫 2017-04-18 10:51:04
0
3
1186

问题1:
想写个requestInfo的toString方法,把所有的成员变量都打印出来,子类就不用每次都写个toString方法了,但是父类怎么获取子类成员变量的值?

public class RequestInfo
{
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        Field[] fields = this.getClass().getDeclaredFields();
        for(Field field : fields)
        {
            sb.append(field.getName(), " = ", (这里怎么获取属性值?), ";");
        }
        return "";
    }
}

问题2
下面那个类P怎么实例化,也没懂错误的原因,用P.getClass()还是不行

public abstract class AbstractService<Q extends RequestInfo, P extends ResponseInfo>
{
    public static final Logger LOGGER = LoggerFactory.getLogger(AbstractService.class);

    private String logTag;

    private P respBean;

    public P execute(Q reqBean)
    {
        init();
        LOGGER.info(StringUtil.appendStr("Request : {}, req = {}", logTag, reqBean.toString()));

        try
        {
            if (checkInput(reqBean))
            {
                handle(reqBean, respBean);
            }
            else
            {
                throw new Exception(StringUtil.appendStr(logTag, " check input param invalid"));
            }
        }
        catch (Exception e)
        {
            LOGGER.error(StringUtil.appendStr(logTag, " Exception: "), e);
        }
        return respBean;
    }

    protected void init()
    {
        logTag = getClass().getSimpleName();
        respBean =P.class.newInsance();//这里报错,cannot select from a type variable
    }

    protected boolean checkInput(Q reqBean)
    {
        return true;
    }

    protected abstract void handle(Q reqBean, P respBean)
            throws Exception;
}
迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

répondre à tous(3)
PHPzhong

Les génériques ont été effacés après la compilation. Le jvm ne peut pas du tout voir les informations génériques. Cela est dû à des raisons historiques, donc le p.getClass que vous avez mentionné ne peut pas exister

.

La première question est une bonne idée, mais pour autant que je sache, elle ne peut pas être réalisée. L'objet ne peut pas connaître l'état de la sous-classe. Le mécanisme polymorphe de Java ne peut apprendre que de la classe parent ou de la classe parent. méthodes dans l'interface

Je suppose que la première question est que vous pensez pouvoir obtenir les variables membres d'une sous-classe parce que vous pensez qu'une fois la méthode toString de la sous-classe exécutée après l'héritage, la vôtre sera également appelée. faux. Au moment de l'exécution, le jvm obtiendra cette méthode à partir de l'espace objet de la classe parent et l'exécutera. Par conséquent, quoi qu’il arrive, ce ne sont que des variables membres de la classe parent

J'ai fait une erreur dans la partie en italique ci-dessus. Après avoir exécuté l'EDI pour le tester, j'ai découvert que j'avais tort sur ce que j'avais compris auparavant. J'espère que cela n'a pas causé de problèmes à la personne qui pose la question.
Le code publié ci-dessous peut boucler pour obtenir toutes les variables de la sous-classe à la classe parent. J'espère que cela aide

public String toString() {
        StringBuilder sb = new StringBuilder();
        Class clazz = this.getClass();
        while(clazz.getSuperclass() != null){
            Field[] fields = clazz.getDeclaredFields();
            try {
                for (Field field : fields) {
                    field.setAccessible(true);
                    sb.append(field.getName()).append("=").append(field.get(this))
                        .append("\n");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            clazz = clazz.getSuperclass();
        }
        
        return sb.toString();
    }
刘奇

Classe d'outils de réflexion

package cn.hylexus.app.util;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ReflectionUtils {

    public static List<Field> getFields(Class<?> clz) {
        List<Field> ret = new ArrayList<>();
        for (Class<?> c = clz; c != Object.class; c = c.getSuperclass()) {
            Field[] fields = c.getDeclaredFields();
            ret.addAll(Arrays.asList(fields));
        }
        return ret;
    }

    /**
     * @param cls
     *            子类对应的Class
     * @param index
     *            子类继承父类时传入的索引,从0开始
     * @return
     */
    public static Class<?> getSuperClassGenericType(Class<?> cls, int index) {
        if (index < 0)
            return null;

        Type type = cls.getGenericSuperclass();
        if (!(type instanceof ParameterizedType))
            return null;

        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type[] typeArguments = parameterizedType.getActualTypeArguments();
        if (typeArguments == null || typeArguments.length == 0 || index > typeArguments.length - 1)
            return null;

        Type t = typeArguments[index];
        if (!(t instanceof Class)) {
            return null;
        }
        return (Class<?>) t;
    }

    public static Class<?> getSuperClassGenericType(Class<?> cls) {
        return getSuperClassGenericType(cls, 0);
    }
}

Question 1

public class RequestInfo {

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        //可以拿到多层次基础的属性
        List<Field> fields = ReflectionUtils.getFields(this.getClass());
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                sb.append(f.getName()).append("=").append(f.get(this)).append("\n");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}

Question 2

    @SuppressWarnings("unchecked")
    protected void init() {
        logTag = getClass().getSimpleName();
        try {
            //这里可以拿到动态绑定的Class信息
            Class<?> clz = ReflectionUtils.getSuperClassGenericType(this.getClass(), 1);
            respBean = (P) clz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
刘奇

Le premier problème peut être résolu en utilisant commons-beanutils.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal