有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

考虑类:

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()));

以上两行都有no编译错误和no异常抛出

O.M.G.-有没有更好的方法来强制执行类型参数


共 (1) 个答案

  1. # 1 楼答案

    欢迎来到type erasure。在运行时,Class<T>擦除到Class-到JVM,源代码中的内容aClass<Integer>Class<String>等等。所有这些看起来都是一样的。这就是unchecked cast的含义——开发人员这样做的风险由他或她自己承担,因为如果ClassCastException错误,它不会快速失败。相反,在类型擦除过程中编译器插入的强制转换中,可能会出现一些稍后的ClassCastException。这种状态称为heap pollution,在这种状态下,泛型类型的引用指向不应该允许的对象

    O.M.G. - any better way to enforce the Type Argument?

    不,就泛型类型安全而言,这是Java所能提供的最好的——它实际上是选择性加入。懒惰或滥用的代码可以自由地执行未经检查的强制转换或使用raw types(这会将隐式未经检查的强制转换带到它们接触的任何对象),尽管许多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")删除未检查的警告,本质上是告诉编译器信任我们。添加解释性注释也是一个好主意