2013-12-11 36 views
3

有没有什么办法可以在运行时创建泛型类型的特定实例?Java泛型 - 我可以根据变量类型动态创建列表

例如。

Cacheable instance = getCacheable(someInput); 

getCacheble方法将返回Cacheable的实例。所以它可以是任何实现Cacheable的类,例如客户,产品等。现在我想创建一个由getCacheable返回的特定类型的列表,如下所示。这可能吗?如果是的话该怎么做?

List<? extends Cacheable> cacheList = new ArrayList<>(); 

我想根据getCacheable方法返回的实例创建ArrayList<Product> or ArrayList<Customer>

+1

由于力擦除这有点不合理,因为名单没有按在运行时没有类型。泛型是用于编译时检查。所以真正的答案取决于你的实际使用情况。你为什么要编译时间检查和如何?在运行时,你可以把任何东西放在任何列表中,泛型只是作为看门人。 – Radiodef

回答

6

你可以这样做:因为类型擦除

Cacheable instance = getCacheable(someInput); 
List<? extends Cacheable> l = new ArrayList<>(); 
l = Collections.checkedList(l, instance.getClass()); 

,在编译时访问的所有信息在运行时丢失。 checkedList方法将确保您的列表将只接收instance变量类的实例。

UPDATE: 你也可以这样做:

public static <T extends Cacheable> MyOwnCustomGeneric<T> createMyOwnCustomGeneric(Class<T> type) { 
    return new MyOwnCustomGeneric<T>(); 
} 

// ... 
IMyOwnCustomGeneric foo = createMyOwnCustomGeneric(instance.getClass()); 
+0

感谢您的回答。问题是我实际上并没有使用List,它是我自己的自定义泛型类。我以List作为示例来简化prob语句。 – JRR

+0

@Jai你自己定制的泛型类是一个'Collection'(http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html)?如果是这样,你可以使用'checkedCollection'而不是'checkedList'。 – Stephan

+0

否Alex.Its不收集。我想在这里避免支票的实例,但我认为它不可能。 – JRR

0
if (instance instanceof Product) { 
    // create ArrayList<Product>; 
} else { 
    // create ArrayList<Customer>; 
} 

这是不是真的一般,动态不过。

+1

但我更喜欢Alex的回答。 –

0

做到这一点的唯一方法是通过对instance类型的开关,但没有太多,你可以用它做:

List<? extends Cacheable> cacheList = null; 
if (instance instanceof Product) 
    cacheList = new ArrayList<Product>(); 
// etc 

但是你能对这个名单吗?你不能添加任何东西。也许你在创建它时添加了项目,但这可能不是用例,因为它是一个缓存列表。

如果您需要稍后添加项目,请参阅this answer是正确的方法。

如果你不打算在以后添加的项目,它不一样,如果类型是List<Cacheable>List<? extends Cacheable>重要

2

使用通用的辅助功能:

public static <T extends Cacheable>ArrayList<T> createList(Class<T> claz) 
{ 
     return new ArrayList<>(); 
} 

ArrayList<? extends Cacheable>alist = createList(instance.getClass()); 
+0

请注意,参数'claz'没有使用,可以删除。 –

+0

@PaulBellora,是不是需要从实例自己的类型推断出类型。我明白,因为'alist'的类型是'ArrayList <?扩展Cacheable>'不需要 – Sage

+0

类型推断是在编译时发生的事情。如果失败,可以用例如手动指定类型参数。 'MyClass的。 createList()'。但考虑到泛型在运行时已经被擦除,OP所要求的是没有意义的。 'createList(instance.getClass())'可以简化为'new ArrayList ()',因为在运行时它只是'ArrayList'。 –