类参数检查的通用类型参数可以被黑客攻击,任何更好的方法? [英] Generic Type Argument checked by Class Parameter can be hacked, any better ways?

查看:130
本文介绍了类参数检查的通用类型参数可以被黑客攻击,任何更好的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑类:

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

它只接受类型参数 Integer 。我们在其构造函数中添加了 if-throw 检查。这是一种非常常见的检查类型参数的方法。

It is designed to accept only Type Arguments of Integer. We have added a if-throw check in its constructor. This is a very common way to check the Type Arguments.

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

However, this checking can be bypassed (hacked, fooled) by:

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

两者编译错误和没有异常抛出!

Both the above two lines have no compile-errors and no exceptions thrown!

OMG -

推荐答案

欢迎来到类型擦除。在运行时,类< T> 已被擦除 Class 在源代码中 Class< Integer> Class< String> 等都是相同的。这是 取消选中投放 - 开发人员会自行处理,因为 c> ClassCastException 如果它错了。相反,在类型擦除过程期间,编译器插入的转换可能会出现一些后来 ClassCastException 。这种状态称为堆污染

Welcome to type erasure. At runtime, Class<T> has been erased to Class - to the JVM, what was in the source code a Class<Integer>, Class<String>, etc. all look the same. This is the meaning of an unchecked cast - the developer does it at his or her own peril, because it will not fail fast with a ClassCastException if it's wrong. Instead, some later ClassCastException may occur instead, at a cast that was inserted by the compiler during the type erasure process. This state, in which generically-typed references are pointing to objects they shouldn't have been allowed to, is known as heap pollution.


OMG - 任何更好的方式强制类型参数?

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

不,这是最好的Java可以提供的通用类型安全 - 真的是选择加入。懒惰或滥用代码可免费进行未选中的投射或使用原始类型(将隐式未经检查的转换带到任何他们碰到的东西),虽然许多IDE提供这些编译器错误,而不是警告。

No, this is the best Java can offer in terms of generic type safety - it really is opt-in. Lazy or abusive code is free to do unchecked casts or use raw types (which bring implicit unchecked casts to anything they touch), although many IDEs offer to make these compiler errors instead of warnings.

例如在实现Joshua Bloch的Effective Java项目27赞成通用方法时:

As a side note, unchecked casts are occasionally valid, for example when implementing Joshua Bloch's Effective Java item 27, "favor generic methods":

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 表现为违反规定。它是无状态的并且适用于任何 Object ,所以我们可以让调用者决定它的泛型类型:

Here, the unchecked cast is safe because HASH_CODE_COMPARATOR behaves contravariantly. It's stateless and works for any Object, so we can let the caller decide its generic type:

Comparator<String> c = hashCodeComparator();

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

In this case we can use @SuppressWarnings("unchecked") to remove the unchecked warning, essentially telling the compiler to trust us. It's also a good idea to add an explanatory comment.

这篇关于类参数检查的通用类型参数可以被黑客攻击,任何更好的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆