【问题标题】:How to get the class of a field on a generic object when field is referenced by string name字符串名称引用字段时如何获取通用对象上字段的类
【发布时间】:2017-02-08 20:11:55
【问题描述】:

我有一个方法,它接受一个对象和一个字符串(字符串是对象上的一个字段的名称)。所以我从对象类中获取字段并使用 field.get(object) 来获取值。但我想将该值转换为该字段定义为的任何类。有没有办法在不需要使用@suppressWarnings("unchecked") 的情况下进行强制转换?

这是我的代码。我将它缩短为只使用一个对象,但原始使用了一个对象列表并返回一个映射,其中 map-keys 是字段的对象值,而 map-values 是对象。

public static <T1,T2> T2 getFieldValue(T1 obj, String fieldName){
    Field field = null;
    T2 value = null;
    try {
        field = obj.getClass().getField( fieldName );
    } catch ( NoSuchFieldException e ) { ... }
    if ( field != null ){
        try {
            value = (T2)field.get(obj);  // <--- unchecked cast!!!
        } catch ( IllegalAccessException e ) { ... }
    }
    return value;
}

【问题讨论】:

    标签: java generics nested-generics


    【解决方案1】:

    如果可能,我建议为T2 类传递一个参数。通过传入Class&lt;T2&gt;,您可以调用cast 方法。如果强制转换无效,此方法将抛出 ClassCastException。这也将删除未经检查的警告消息。

    public static <T1, T2> T2 getFieldValue(T1 obj, String fieldName, Class<T2> cls) {
        Field field = null;
        T2 value = null;
        try {
            field = obj.getClass().getField(fieldName);
        } catch (NoSuchFieldException e) {
        }
        if (field != null) {
            try {
                value = cls.cast(field.get(obj));  // <---  no unchecked cast!!!
            } catch (IllegalAccessException e) {
            } catch (ClassCastException e) {
            }
        }
        return value;
    }
    

    【讨论】:

    • +1 用于使用 Class.cast(),但 -1 用于空 catch 块。捕捉ReflectiveOperationException 之类的东西并用它做一些更有用的事情可能会很好,即使它重新抛出它,包裹在IllegalArgumentException 或其他东西中。
    • 确实应该以某种方式处理异常;但是,我将它们留空,因为原始示例也将它们留空。唯一的区别是我删除了“...”以便代码可以编译。
    • value = cls.cast(field.get(obj)); 不安全。警告只是被移开并被压制了。它给人一种安全代码的印象,而实际上并非如此。我更喜欢带有显式 @suppressWarnings 的显式强制转换,它传达了方法的不安全方面。
    • @davidxxx Class.cast() 尽可能安全。向下转换总是会导致错误。使用 @SuppressWarnings 和显式强制转换是一种完全有效的方法。但是,此方法没有明确说明可以抛出 ClassCastExceptionClass.cast() 在 JavaDoc 中声明可以抛出 ClassCastException。这意味着该方法并不总是安全的,它会明确告诉您在发生错误时要捕获的异常。
    • @davidxxx 我完全同意你的观点,即抑制是一个有效的选择。但是,当使用抑制时,忽略ClassCastException 是错误的。它可能是未经检查的异常,但仍需要处理。当你说的只是压制警告时,我说错了。需要通过执行以下一项或多项选项来处理异常:1)在 javadoc 中记录,2)添加到 throws,3)捕获异常。我觉得你可以很容易地用压制来打自己的脚,应该非常小心地使用它。
    猜你喜欢
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 1970-01-01
    • 2011-12-17
    • 2013-09-30
    • 2017-05-08
    相关资源
    最近更新 更多