Java在匿名类定义中引用Enum类型

时间:2014-01-21 02:21:50

标签: java generics enums anonymous-class

我正在尝试定义以下匿名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;      
}

第一个,匿名类定义不行。第二个非匿名方法定义是OK。

无论如何使用Enums定义匿名类?

由于

3 个答案:

答案 0 :(得分:4)

作为Sotirios points out,泛型类型参数只能为类或方法而不是字段声明。事实上,声明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;
    }
};

遵循这一思路,toStringObject宣布,而不是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接受任何对象并且是无国籍的。这种模式在Joshua Bloch的Effective Java第27项“赞成泛型方法”中得到了证明。

答案 1 :(得分:2)

您不能在任何地方使用泛型类型变量。您必须处于可以声明且可访问的上下文中。

在第二个示例中,它们在方法签名中声明。

在您的第一个示例中,似乎E在任何地方都没有声明。换句话说,您不能将类型变量声明为变量声明的一部分。如果代码片段中出现的方法或类声明了类型变量E本身,那么你可以做你正在尝试的事情。

答案 2 :(得分:0)

你可能根本不需要泛型,因为你实际上并没有使用类型信息,而且它在运行时也会丢失。首先使用old-school Function apply(Enum enumValue)开始。如果你真的不想压制警告并需要进行类型检查,那么你可以从那里进一步调查。