我正在使用开放式API(因此无法更改其一侧的代码),该API提供了一系列枚举值类型。
User.IDType.values();
问题适用于上述数组中的每种类型。我必须调用value()函数来为提供的类型返回String值的数组。
public static String[] enumValues(IDType[] types) {
String[] values = new String[types.length];
for ( int i=0; i < types.length; i++ ) {
values[i] = types[i].value();
}
return values;
}
为了避免为每种类型编写此函数,我想编写如下的通用方法,但问题是:如何为通用类型调用函数值?
static <T> String[] enumValues(T[] types)
{
String[] values = new String[types.length];
for (int i=0; i<types.length; i++) {
values[i] = types[i].value;
}
return values;
}
注意:任何类型都没有超类,例如:Type,我可以 使用。
答案 0 :(得分:0)
通常,在声明类型变量时将其上限:
<T extends SomeType>
然后,您可以在方法主体中T类型的引用中从SomeType
调用方法/访问字段。
但是,泛型对此方法一无所获。数组是协变的,因此您可以传递为什么元素类型为IDType
的子类型的数组。
请勿混合使用泛型和数组。
答案 1 :(得分:0)
由于您有以下限制:
任何类型都没有超类,例如:我可以使用的类型。
剩下的解决方案是使用反射API。
但是,当更改value
方法时,这种解决方案是不安全类型,运行时错误,而不是编译时错误在枚举中。以下是使用反射API的示例。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class GenericEnumTest {
static <T> String[] enumValues(T[] types) {
String[] values = new String[types.length];
for (int i = 0; i < types.length; i++) {
Method valueMethod;
try {
valueMethod = types[i].getClass().getMethod("value");
values[i] = (String) valueMethod.invoke(types[i]);
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException | IllegalAccessException
| InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return values;
}
public static void main(String[] args) {
String[] result = enumValues(new IDType[] { IDType.TEST1, IDType.TEST2 });
System.out.println(Arrays.toString(result));
}
public static enum IDType {
TEST1("test1"), TEST2("test2");
private IDType(String value) {
this.value = value;
}
private String value;
public String value() {
return value;
}
}
}
答案 2 :(得分:0)
您可以使用Function<T, String>
作为映射器从枚举值实例中提取String
值。该映射器函数将如下传递给enumValues
:
public static <T> String[] enumValues(T[] types, Function<T, String> mapper) {
String[] values = new String[types.length];
for (int i = 0; i < types.length; i++) {
values[i] = mapper.apply(types[i]);
}
return values;
}
用法很简单:
String[] ids = enumValues(User.IDType.values(), t -> t.value);
之所以可行,是因为从提供的枚举值数组的component type推断出映射器函数T
的类型。因此t
是一个枚举值实例,我们可以使用t
的每个可见成员-在这种情况下为value
。
只要每个枚举值都有一个公共字段value
,就可以使用t -> t.value
。如果您使用方法value()
代替字段value
,则可以编写t -> t.value()
,它等效于User.IDType::value
。这表明显式的映射器函数取决于类型T
。因此,如果枚举值类型不提供公共字段value
,则映射t -> t.value
将导致编译时错误。这意味着这种方法是类型安全的。
编辑
使用Stream-API,您可以按以下方式重写enumValues
:
public static <T> String[] enumValues(T[] types, Function<T, String> mapper) {
return Arrays.stream(types).map(mapper).toArray(String[]::new);
}