繁体   English   中英

通过类参数检查的泛型类型参数可以被黑,还有更好的方法吗?

[英]Generic Type Argument checked by Class Parameter can be hacked, any better ways?

考虑一下类:

class OnlyIntegerTypeAllowed<T> {
    OnlyIntegerTypeAllowed(Class<T> clazz) {
        System.out.println(clazz);
        if (clazz != Integer.class)
            throw new RuntimeException();
    }
}

它被设计为仅接受Integer类型参数。 我们在其构造函数中添加了一个if-throw检查。 这是检查类型参数的一种非常常用的方法。

但是,可以通过以下方式绕过(检查,欺骗)此检查:

OnlyIntegerTypeAllowed<Integer> normalWay =
        new OnlyIntegerTypeAllowed<Integer>(Integer.class);
OnlyIntegerTypeAllowed<String> hacking =
        new OnlyIntegerTypeAllowed<String>((Class<String>) Class.forName(Integer.class.getName()));

上述两种线都没有编译错误和没有抛出异常!

OMG-有什么更好的方法来执行类型参数?

欢迎进行擦除 在运行时, Class<T>已被擦除Class -JVM,源代码中的Class<Integer>Class<String>等都看起来相同。 这就是未经检查的强制转换的意思-开发人员要自己承担风险,因为如果错误的话,它不会ClassCastException 快速失败。 取而代之的是,稍后的ClassCastException可能会在类型擦除过程中由编译器插入的强制转换中发生。 通用类型的引用指向不应该允许的对象的状态称为堆污染

OMG-有什么更好的方法来执行类型参数?

不,就泛型类型安全而言,这是Java所能提供的最好的-实际上它是可选的。 懒惰或滥用代码可以随意执行未经检查的强制转换或使用原始类型 (将隐式未经检查的强制转换引入其所触摸的任何内容),尽管许多IDE都提供使这些编译器错误而不是发出警告的功能。

附带说明一下,未经检查的强制转换有时是有效的,例如,在实现Joshua Bloch的有效Java项目27“偏爱的通用方法”时:

private static final Comparator<Object> HASH_CODE_COMPARATOR =
        new Comparator<Object>() {
            @Override
            public int compare(final Object o1, final Object o2) {
                return Integer.compare(o1.hashCode(), o2.hashCode());
            }
        };

public static <T> Comparator<T> hashCodeComparator() {
    @SuppressWarnings("unchecked") // this is safe for any T
    final Comparator<T> withNarrowedType =
            (Comparator<T>)(Comparator<?>)HASH_CODE_COMPARATOR;
    return withNarrowedType;
}

在这里,选中转换是安全的,因为HASH_CODE_COMPARATOR行为contravariantly 它是无状态的,并且适用于任何Object ,因此我们可以让调用者确定其通用类型:

Comparator<String> c = hashCodeComparator();

在这种情况下,我们可以使用@SuppressWarnings("unchecked")删除未经检查的警告,从本质上告诉编译器信任我们。 添加解释性注释也是一个好主意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM