Rumah  >  Soal Jawab  >  teks badan

java - 关于泛型和反射的代码错误(cannot select from a type variable)

问题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;
}
迷茫迷茫2743 hari yang lalu1099

membalas semua(3)saya akan balas

  • PHPz

    PHPz2017-04-18 10:53:04

    Generik telah dipadamkan selepas kompilasi Jvm tidak dapat melihat maklumat generik sama sekali Ini disebabkan oleh sebab sejarah, jadi p.getClass yang anda nyatakan tidak boleh wujud

    Soalan pertama adalah idea yang bagus, tetapi sejauh yang saya tahu, ia tidak boleh direalisasikan kaedah dalam antara muka

    Saya rasa soalan pertama ialah anda fikir anda boleh mendapatkan pembolehubah ahli subkelas kerana anda berpendapat bahawa sebaik sahaja kaedah toString subkelas dilaksanakan selepas pewarisan, anda sendiri ini juga akan dipanggil salah. Pada masa berjalan, jvm akan memperoleh kaedah ini daripada ruang objek kelas induk dan melaksanakannya. Oleh itu, tidak kira apa pun, mereka hanyalah pembolehubah ahli kelas induk

    Saya membuat kesilapan dalam bahagian yang dicondongkan di atas Selepas menjalankan IDE untuk mengujinya, saya mendapati bahawa saya salah tentang apa yang saya fahami sebelum ini.
    Kod yang disiarkan di bawah boleh gelung untuk mendapatkan semua pembolehubah daripada subkelas kepada kelas induk. Semoga ini membantu

    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();
        }

    balas
    0
  • 怪我咯

    怪我咯2017-04-18 10:53:04

    Kelas alat refleksi

    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);
        }
    }

    Soalan 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();
        }
    }

    Soalan 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();
            }
        }

    balas
    0
  • 怪我咯

    怪我咯2017-04-18 10:53:04

    Masalah pertama boleh diselesaikan menggunakan commons-beanutils.

    balas
    0
  • Batalbalas