我正在尝试做这样的事情:
1。方法
Type ty = entityType.getEntityClass(); // could be e.g. String.class
List<ty> list;
2。方法
Class cl = entityType.getEntityClass(); // could be e.g. String.class
List<cl> list;
然而,编译器只是说&#34; no&#34;。
有没有办法设置例如<T>
的泛型类型java.util.List动态只有通过例如String.class
或foo.getClass()
?
...
我实际上要做的是按照EntityTypeEnum
类型的给定参数或它的Class
属性值初始化List。
public enum EntityTypeEnum {
ARTICLE(Article.class),
ORDER(OrderHeader.class),
CUSTOMER(Customer.class),
CUSTOMER_SESSION(CustomerSession.class);
private final Class entityClass;
private EntityTypeEnum(final Class entityClass) {
this.entityClass = entityClass;
}
public Class getEntityClass() {
return entityClass;
}
}
建设性的批评是受欢迎的。 谢谢!
添加:(作为Andy评论的回应)
Class cl = String.class;
List<cl> list;
..也不起作用!
List<String> list;
..当然有用。
那么String
和String.class
之间有什么区别?
或者有没有办法将值设置为:
public enum EntityTypeEnum {
ARTICLE(Article)
..
答案 0 :(得分:4)
您误解了Java泛型的功能:您无法根据变量的值执行某些操作,只能使用变量的类型。< / p>
基本上,Java泛型只是强制类型转换:编译器会自动为您插入强制转换,并检查这些强制转换所产生的类型是否匹配。
你可以做你在你的例子中描述的,但不是使用枚举。 Java中枚举的缺点之一是所有元素都具有相同的类型。
您可以使用大致看起来像枚举的内容,而不是使用真实的枚举:
final class EntityTypeEnumIsh {
private EntityTypeEnumIsh() {}
static final EntityClassSupplier<Article> ARTICLE =
new EntityClassSupplier<>(Article.class);
static final EntityClassSupplier<OrderHeader> ORDER =
new EntityClassSupplier<>(OrderHeader.class);
// ...
final class EntityClassSupplier<T> {
private final Class<T> clazz;
EntityClassSupplier(Class<T> clazz) { this.clazz = clazz; }
Class<T> getEntityClass() { return clazz; }
}
}
您现在可以在描述的方法中使用这些:
<T> List<T> method(EntityClassSupplier<T> supplier) {
return new ArrayList<>();
}
并像这样调用:
List<Article> list = method(EntityTypeEnumIsh.ARTICLE);
当然,你没有获得“真实”枚举的所有优点(如序列化,抵抗反射攻击等)。但是你得到了其他有用的东西,所以要根据你的用例进行衡量。
答案 1 :(得分:1)
它不起作用,因为泛型是一个编译时的概念,但你试图将它用作运行时概念。
不同之处在于,对于编译时概念,编译器需要能够根据代码中的信息确定类型(即,不运行或评估它)。
这里的代码在语法上是正确的:
public enum EntityTypeEnum
{
ARTICLE(String.class), // just using some builtin types to demonstrate
ORDER(Integer.class),
CUSTOMER(Double.class),
CUSTOMER_SESSION(Short.class);
private final Class<?> entityClass;
private EntityTypeEnum(final Class<?> entityClass)
{
this.entityClass = entityClass;
}
public Class<?> getEntityClass()
{
return this.entityClass;
}
}
class Test
{
// here, T is the type parameter which is determined from the class type
public <T> List<T> createList(final Class<T> clazz)
{
return new ArrayList<T>();
}
// this is the demo code on how to use it
public void foo()
{
EntityTypeEnum t = EntityTypeEnum.ARTICLE;
List<?> list = createList(t.getEntityClass());
}
}
问题是这对你没有多大帮助。列表与List大致相同。编译器不能将类型缩小到特定的包含对象类,因为它取决于运行时。
对于您的情况,如果您的元素有一个共同的超类,您可以使用此信息来缩小类型:
public enum EntityTypeEnum
{
ARTICLE(Article.class),
ORDER(OrderHeader.class),
CUSTOMER(Customer.class),
CUSTOMER_SESSION(CustomerSession.class);
private final Class<? extends CommonParent> entityClass;
private EntityTypeEnum(final Class<? extends CommonParent> entityClass)
{
this.entityClass = entityClass;
}
public Class<? extends CommonParent> getEntityClass()
{
return this.entityClass;
}
}
class Test
{
public <T extends CommonParent> List<T> createList(final Class<T> clazz)
{
return new ArrayList<T>();
}
public void foo()
{
EntityTypeEnum t = EntityTypeEnum.ARTICLE;
List<? extends CommonParent> list = createList(t.getEntityClass());
}
}
但是如果你有一个共同的父母,上面的代码没有好处而只是写作:
List<CommonParent> list = new ArrayList<CommonParent>();
并跳过所有其他通用内容...