I have the following class structure:
abstract class Role;
class Employee extends Role;
class Student extends Role;
class Employer extends Role;
Also I have an enum in which I store the acceptable roles.
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;
}
}
What I want is to get an array of elements of type Class<? extends Role>
from a list of RoleEnums. I am using FluentIterable from Guava libraries and what I am trying to do is something like FluentIterable.from(list).transform(function).toArray(Class<? extends PartyRole>)
. However what I managed to do is a workaround and kinda of a hack. It looks something like this:
(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]));
where
class RoleComboWidget<R extends Role>
is the class from where I call the method and
ImmutableList<RoleEnum> roles;
What you see is the effect of combining arrays with generics. Arrays in Java are fully typed at runtime: the component type is available at runtime and load/store operations are type checked and may throw exceptions.
This requires the component type to be a reifiable type, but parameterized types like RoleComboWidget<W>
are not. Generics are implemented in Java via invisible casts added at compile time, but once the program is running the JVM actually doesn't know if that is a List<String>
or a List<Integer>
.
Back to your problem, if you are in control of the API, be careful when requiring arrays instead of Collection (or Stream): rarely the benefits (usually in performance) outperform the drawbacks (usually in source-code maintenance). Also, be warned (the compile already warns you) that the cast to SomeParameterizedType<T>[]
is always unchecked: as per the things explained earlier, you could end up with objects of the wrong type that may screw up or even halt your program.