不需要输入泛型,如何检索泛型类型的类实例

3

我有一个类:

public abstract class BaseDaoImpl<T extends BaseModel> implements BaseDao<T> {
}

我还在使用注解生成SQL查询(由于某些原因,我无法使用诸如Hibernate之类的框架),例如@Table和@Column。

我希望能够在不需要将T作为方法输入的情况下检索<T extends BaseModel>.class实例。

我想简便的替代方法是创建一个方法:

public void set(Class<T> clazz){}

但我希望尽可能避免这种情况,以保持我的代码尽可能简洁。这是否可行?

2个回答

4
虽然使用反射有些不太好,但是你可以获取所需的信息:
Class<T> modelImplementationClass = (Class<T>)
   ((BaseModel)this.getClass().getGenericSuperclass())
      .getActualTypeArguments()[0];

反射是Java API的一部分,它允许您在运行时访问或修改方法、类、接口的行为。

通常应避免使用反射,因为它非常缓慢,并通过揭示内部实现细节来打破抽象性。


我尝试使用代码片段并感到困惑:我们想从具体的DAO中提取参数信息,而不是从模型类中提取,对吗?对于此代码片段:final ConcreteDao concreteDao = new ConcreteDao(); System.out.println((concreteDao.getClass().getGenericSuperclass())); System.out.println((concreteDao.getClass().getGenericInterfaces()[0]).getTypeName());您将获得以下输出:class java.lang.Object com.github.gstromov.leetcode.open.easy.BaseDao - The Rabbit of No Luck

4
很遗憾,由于类型擦除的原因,这是不可能实现的type erasure: 你必须强制你的类在运行时提供元信息。我会像这样做(从一个大型真实项目中改编的片段)。
public abstract class AbstractBaseDao<T extends BaseModel> implements BaseDao<T>{

    public abstract Class<T> getType();
}

class ConcreteModel extends BaseModel {/*...*/}

class ConcreteDao extends AbstractBaseDao<ConcreteModel> {

    @Override
    public Class<ConcreteModel> getType() {
        return ConcreteModel.class;
    }
}


一种替代方法是定义一个自定义注解,如下所示:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Type {

    Class value();
}

interface BaseDao<T extends BaseModel> { }

@Type(ConcreteModel.class)
public class ConcreteDao implements BaseDao<ConcreteModel> { }

你可以使用它在DAO中的某些处理器中,但这需要一些额外的基础设施代码来注册所有注释类。并且 - 再次强调 - 你不能在注释中限制类型边界


这里有一个相关的线程:https://dev59.com/vXA75IYBdhLWcg3wPmZ8?rq=1 - The Rabbit of No Luck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接