2016-03-08 20 views
0

列表阵列I具有如下类结构:流利可迭代从包含泛型类

abstract class Role; 
class Employee extends Role; 
class Student extends Role; 
class Employer extends Role; 

另外我有在其中予存储可接受的角色的枚举。

public enum RoleEnum 
{ 
     EMPLOYEE ("Employee", Employee.class), 
     STUDENT ("Student", Student.class), 
     EMPLOYER ("Employer", Employer.class); 

     final private String name; 

     final private Class<? extends Role> pRoleClass; 

     private RoleEnum(final String name, final Class<? extends Role> pRoleClass) 
     { 
      this.name = name; 
      this.pRoleClass = pRoleClass; 
     } 
} 

我要的是从RoleEnums名单得到Class<? extends Role>类型的元素的数组。我正在使用Guava图书馆的FluentIterable,我正在尝试的是类似FluentIterable.from(list).transform(function).toArray(Class<? extends PartyRole>)的东西。然而,我设法做的是一种解决方法和一种黑客行为。它看起来是这样的:

(Class<R>[]) FluentIterable.from(roles) 
         .transform(new Function<RoleEnum, Class<R>>() 
         { 
          @Override public Class<R> apply(final RoleEnum role) 
          { 
           return (Class<R>) role.getRoleClass(); 
          } 
         }) 
         .toList().toArray(new Class[0])); 

其中

class RoleComboWidget<R extends Role> 

是从那里我调用该方法的类和

ImmutableList<RoleEnum> roles; 
+1

我不确定在这里看到一个问题。另外,就它的价值而言,泛型和数组之间基本上的任何交互都需要这样的hackery。泛型和数组真的不能很好地混合。 –

+0

为什么你不会像'返回Collections.stream(RoleEnum.values())。map(enumVal - > enumVal.pRoleClass).toArray(Class <?extends Role> :: new);'在Java 8中代替? – Neil

+0

我们仍然在使用Java 7,希望当我们迁移到Java 8时,使用lambda表达式和Java 8的所有强大工具,事情会更加美好。 –

回答

1

你看到的是阵列泛型相结合的效果。 Java中的数组在运行时完全键入:组件类型在运行时可用,加载/存储操作类型检查并可能会引发异常。

这需要组分型是一个reifiable型,但参数化类型等RoleComboWidget<W>不是。泛型是在Java中通过在编译时添加的不可见转换实现的,但是一旦程序运行,JVM实际上不知道这是否是List<String>List<Integer>。回到你的问题,如果你在控制API,当需要数组而不是集合(或流)时要小心:很少有好处(通常在性能上)优于缺点(通常在源代码维护中) 。另外,要警告(编译已经警告你),对SomeParameterizedType<T>[]的转换总是不被检查:根据前面解释的事情,最终可能会出现错误类型的对象,这些对象可能会使程序崩溃甚至停止。