【问题标题】:How to get rid of this generics warning?如何摆脱这个泛型警告?
【发布时间】:2010-07-12 10:35:46
【问题描述】:

我正在尝试模拟一个通用接口,每当我模拟它时,我都会收到以下警告:

GenericInterface 类型的表达式需要未经检查的转换才能符合 GenericInterface

我的界面是

interface GenericInterface<T>{
    public T get();
}

我的测试是

@Test
public void testGenericMethod(){
    GenericInterface<String> mockedInterface = EasyMock.createMock(GenericInterface.class);
}

我在测试用例的第一行收到警告。

如何删除此一般警告?

【问题讨论】:

    标签: java generics easymock


    【解决方案1】:

    摆脱警告的正确步骤是:

    • 首先,证明未经检查的强制转换是安全的,并记录原因
    • 然后才执行未经检查的强制转换,并在变量声明上注释@SuppressWarnings("unchecked")(而不是在整个方法上)

    所以是这样的:

    // this cast is correct because...
    @SuppressWarnings("unchecked")
    GenericInterface<String> mockedInterface =
        (GenericInterface<String>) EasyMock.createMock(GenericInterface.class);
    

    指南

    以下内容摘自Effective Java 2nd Edition:Item 24: Eliminate unchecked warnings

    • 尽可能消除所有未经检查的警告。
    • 如果您无法消除警告,并且可以证明引发警告的代码是类型安全的,那么(并且仅在那时)使用 @SuppressWarning("unchecked") 注释来抑制警告。
    • 始终在尽可能小的范围内使用SuppressWarning 注释。
    • 每次使用 @SuppressWarning("unchecked") 注释时,请添加注释说明为什么这样做是安全的。

    相关问题


    重构演员表

    在大多数情况下,也可以在泛型 createMock 内执行未经检查的强制转换。它看起来像这样:

    static <E> Set<E> newSet(Class<? extends Set> klazz) {
        try {
            // cast is safe because newly instantiated set is empty
            @SuppressWarnings("unchecked")
            Set<E> set = (Set<E>) klazz.newInstance();
            return set;
        } catch (InstantiationException e) {
            throw new IllegalArgumentException(e);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException(e);          
        }
    }
    

    然后你可以在其他地方简单地做:

    // compiles fine with no unchecked cast warnings!
    Set<String> names = newSet(HashSet.class);
    Set<Integer> nums = newSet(TreeSet.class);
    

    另见

    【讨论】:

    • 征求反馈意见:newSet 中的演员阵容是否被认为是“安全的”?我不认为它实际上是,因为可以创建SpecializedStringSet implements Set&lt;String&gt;,而Set&lt;Integer&gt; nums = newSet(SpecializedStringSet.class); 可以在运行时在add 上抛出ClassCastException,对吧?我将根据 cmets 将其编辑为答案。
    • 你是对的,这是不安全的,这就是你必须禁止警告的原因。
    • @Yishai:它没有被选中,这就是你必须抑制警告的原因。我想知道它是否也不安全。仅仅因为它没有被检查并不意味着它是不安全的。如果它不安全,那么抑制警告是愚蠢的。如果它被证明是安全的,那就压制吧,你就没事了。
    • 您在评论中证明它是不安全的。
    【解决方案2】:

    这里的问题是 EasyMock.createMock() 将返回 GenericInterface 类型的对象,而不是 GenericInterface&lt;String&gt;。您可以使用@SupressWarnings 注释来忽略警告,或者您可以尝试显式转换为GenericInterface&lt;String&gt;(我认为这只是给出了不同的警告。)

    【讨论】:

    • 感谢您的编辑,显然我在转义尖括号或其他方面失败了......
    【解决方案3】:

    似乎在讨论同样的警告......

    我猜@SuppressWarnings 在这种情况下可能是幸福的关键

    【讨论】:

    【解决方案4】:

    如果你真的很想避免编译器警告,你可以在测试中声明一个接口来避免它。

     interface MockGenericInterface extends GenericInterface<String> {}
    

    那么你可以这样做:

     GenericInterface<String> mockedInterface = EasyMock.createMock(MockGenericInterface.class);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-25
      • 2022-11-16
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 2021-11-08
      相关资源
      最近更新 更多