Java:铸造原始包装器 类

Java: casting primitive wrappers classes

我在遍历 JSON 文档中的值时使用了以下方法:

protected static <T> T getValueAs(Object untypedValue, Class<T> expectedType) {
    if (expectedType.isAssignableFrom(untypedValue.getClass())) {
        return (T) untypedValue;
    }
    throw new RuntimeException("Failed");
}

在大多数情况下,它工作得很好,但是当像这样调用时它会失败(抛出异常):

getValueAs((Long) 1L, Double.class);

我知道这是因为 LongDouble 不兼容:

Double d = (Long) 1L; 结果为 error: incompatible types: Long cannot be converted to Double

我想知道即使在这种情况下我是否可以通过某种方式使我的方法起作用 - Long 值被转换为 Double?

我已经看到 isAssignable() from Apache Commons 但我认为它只会使条件工作通过并且在转换时会失败 - 我期望类型 Double 并且值是 Long 类型(不是原语)。

您可能别无选择,只能执行转换。但是由于您的方法不知道如何转换未知 类 的值,您可以将其留作调用者的责任:

protected static <T> T getValueAs(Object untypedValue, Class<T> expectedType) {
    return getValueAs(untypedValue, expectedType, null);
}

protected static <T> T getValueAs(Object untypedValue, Class<T> expectedType, 
                                  Function<Object, T> converter) {
    if (expectedType.isAssignableFrom(untypedValue.getClass())) {

        //use Class.cast to skip unchecked cast warning
        return expectedType.cast(untypedValue); 
    } else if (null != converter) {
        return converter.apply(untypedValue);
    }

    throw new RuntimeException("Failed");
}

调用可能是这样的:

getValueAs(1L, Double.class, v -> ((Number) v).doubleValue());

当然,您可以向 getValueAs() 添加您的方法支持的一些转换,特别是对于最常见的场景;所以你的调用者不必为那些编写转换器。

这个重载方法是否可以接受?

Double n = getValueAs(1L, Number.class, Number::doubleValue);

protected static <P,T> T getValueAs(Object untypedValue, Class<P> expectedType, Function<P, T> f) {
    if (expectedType.isAssignableFrom(untypedValue.getClass())) {
        return f.apply((P)untypedValue);
    }
    throw new RuntimeException("Failed");
}