[英]Java referencing Enum type in anonymous class definition
我正在尝试定义以下匿名Google Guava Function实例:
Function<E extends Enum<E>, String> ENUM_TO_STRING = new Function<E extends Enum<E>, String>() {
@Override
public String apply(E enumValue) {
String result = null;
if (enumValue != null) {
result = enumValue.toString();
}
return result;
}
};
这个想法是一个简单的转换函数实例,带有apply方法,如果不为null,则对任何枚举值调用toString;如果值为null,则返回null。
不幸的是,编译器抱怨通用引用E扩展了Enum。 我知道此表达式可以在非匿名上下文中使用,例如:
public static <E extends Enum<E>> String enumToString(E enumValue) {
String result = null;
if (enumValue != null) {
result = enumValue.toString();
}
return result;
}
第一个匿名类定义不正确。 第二个非匿名方法定义是可以的。
反正有使用Enums定义匿名类的方法吗?
谢谢
正如Sotirios所指出的 ,泛型类型参数只能为类或方法声明,而不能为字段声明。 实际上,声明E
可能是不必要的Function<Enum<?>, String>
就可以了:
Function<Enum<?>, String> ENUM_TO_STRING = new Function<Enum<?>, String>() {
@Override
public String apply(Enum<?> enumValue) {
if (enumValue != null) {
return enumValue.toString();
}
return null;
}
};
按照这种思路, toString
是由Object
而不是Enum
声明的,因此常规的Function<Object, String>
更有意义:
Function<Object, String> NULLABLE_TO_STRING = new Function<Object, String>() {
@Override
public String apply(Object obj) {
if (obj != null) {
return obj.toString();
}
return null;
}
};
通常,最好将实现细节隐藏在工厂方法后面,以使将来的更改更容易,例如:
private static final Function<Object, String> NULLABLE_TO_STRING = ...
public static Function<Object, String> nullableToString() {
return NULLABLE_TO_STRING;
}
请注意,仍在返回Function<Object, String>
。 只要您的API使用PECS (例如,接受Function<? super Foo, ? extends Bar>
),这就可以了,但是我们也可以通过使方法通用来进一步提供特定的输入类型:
private static final Function<Object, String> NULLABLE_TO_STRING = ...
public static <T> Function<T, String> nullableToString() {
@SuppressWarnings("unchecked") // safe contravariant cast
final Function<T, String> withNarrowedType =
(Function<T, String>)(Function<?, String>)NULLABLE_TO_STRING;
return withNarrowedType;
}
请注意,这使用相同的Function
实例,并且未经检查的强制转换会缩小其输入类型。 NULLABLE_TO_STRING
是安全的,因为NULLABLE_TO_STRING
可以接受任何对象并且是无状态的。 此模式在Joshua Bloch的有效Java项目27“喜欢的通用方法”中得到了证明。
您不能在任何地方使用通用类型变量。 您必须处于可以声明它们且可以访问它们的上下文中。
在第二个示例中,它们在方法签名中声明。
在第一个示例中,似乎没有在任何地方声明E
换句话说,您不能将类型变量声明为变量声明的一部分。 如果代码所在的方法或类声明了类型变量E
本身,则可以执行尝试的操作。
您可能根本不需要泛型,因为您实际上并没有使用类型信息,而且无论如何它都会在运行时丢失。 首先从老式的函数apply(Enum enumValue)开始。 如果您确实不想抑制警告并需要类型检查,则可以从那里进一步进行调查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.