在不将通用作为输入的情况下检索通用类型的 Class 个实例
Retrieve Class instance of Generic Type without taking the Generic as an input
我有一个 class:
public abstract class BaseDaoImpl<T extends BaseModel> implements BaseDao<T> {
}
我还使用注解来生成 SQL 查询(由于各种原因我无法使用 hibernate 等框架),例如 @Table & @Column
我希望能够检索 <T extends BaseModel>
.class
实例,而不必将 T
作为方法的输入。
我想简单的替代方法是创建一个方法:
public void set(Class<T> clazz){}
但是我想尽可能避免这种情况,以尽可能简化我的代码。
这可能吗?
不幸的是,由于 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 的某些处理器中使用它,但这将需要一些额外的基础架构代码来注册所有带注释的 类。而且 - 再一次 - 你不能限制 type bounds within annotations.
虽然使用反射有点代码味,但是你可以得到你需要的信息:
Class<T> modelImplementationClass = (Class<T>)
((BaseModel)this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
反射是一种JavaAPI,允许您在运行时访问或修改方法、类、接口的行为。
通常应避免反射,因为它非常慢并且会通过揭示内部实现细节来破坏抽象。
我有一个 class:
public abstract class BaseDaoImpl<T extends BaseModel> implements BaseDao<T> {
}
我还使用注解来生成 SQL 查询(由于各种原因我无法使用 hibernate 等框架),例如 @Table & @Column
我希望能够检索 <T extends BaseModel>
.class
实例,而不必将 T
作为方法的输入。
我想简单的替代方法是创建一个方法:
public void set(Class<T> clazz){}
但是我想尽可能避免这种情况,以尽可能简化我的代码。 这可能吗?
不幸的是,由于 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 的某些处理器中使用它,但这将需要一些额外的基础架构代码来注册所有带注释的 类。而且 - 再一次 - 你不能限制 type bounds within annotations.
虽然使用反射有点代码味,但是你可以得到你需要的信息:
Class<T> modelImplementationClass = (Class<T>)
((BaseModel)this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
反射是一种JavaAPI,允许您在运行时访问或修改方法、类、接口的行为。
通常应避免反射,因为它非常慢并且会通过揭示内部实现细节来破坏抽象。