java中flist cannot_关于泛型和反射的代码错误(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;

}

泛型,在编译之后,就已经被擦除了,jvm根本看不到泛型的信息,这点是由于历史遗留原因导致的,所以你说的p.getClass是不可能存在的

第一个问题,想法很好,但是,据我所知是无法实现的,对象是无法获知子类的情况的,java的多态机制也只能是从父类或者父接口中查询方法

我猜第一个问题你会觉得可以获取子类的成员变量是觉得继承之后子类的toString方法一执行,也会调用自己的this,这是错误的。在运行的时候,jvm会从父类的对象空间获取这个方法并执行。所以,怎么搞都只是父类的成员变量

上述斜体的地方我说错了,开了IDE测试了一下之后,对于自己之前理解的地方有误,希望没造成题主的困扰。

下面贴的这段代码,就可以循环获取从子类到父类的所有变量。希望能有帮助

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

}

反射工具类

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

}

}

问题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();

}

}

问题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();

}

}

第一个问题可以利用commons-beanutils做。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值