开发者

How to get rid of this generics warning?

I am trying to mock a generic interface, and whenever I mock it, I gets this warning:

The expression of type GenericInterface needs unchecked conversion to conform to GenericInterface<String>

My interface is

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

and开发者_运维百科 my test is

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

I get warning at the first line in test case.

How do I remove this generic warning?


The correct steps to get rid of the warning is:

  • First and foremost, prove that the unchecked cast is safe, and document why
  • Only then perform the unchecked cast, and annotate @SuppressWarnings("unchecked") on the variable declaration (not on the whole method)

So something like this:

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

Guidelines

The following is excerpt from Effective Java 2nd Edition: Item 24: Eliminate unchecked warnings:

  • Eliminate every unchecked warning that you can.
  • If you can't eliminate a warning, and you can prove that the code that provoked the warning is typesafe, then (and only then) suppress the warning with @SuppressWarning("unchecked") annotation.
  • Always use the SuppressWarning annotation on the smallest scope possible.
  • Every time you use an @SuppressWarning("unchecked") annotation, add a comment saying why it's safe to do so.

Related questions

  • What is SuppressWarnings (“unchecked”) in Java?
  • How do I address unchecked cast warnings?
  • Type safety: Unchecked cast

Refactoring the cast

It is also possible in most cases to perform the unchecked cast inside a generified createMock. It looks something like this:

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

Then elsewhere you can simply do:

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

See also

  • Java Tutorials/Generics
  • Angelika Langer's Java Generics FAQ


The problem here is that EasyMock.createMock() is going to return an object of type GenericInterface and not GenericInterface<String>. You could use the @SupressWarnings annotation to ignore the warning, or you could try and explicit cast to GenericInterface<String> (I think this just gives a different warning though.)


  • http://www.velocityreviews.com/forums/t147848-generics-in-1-5-nonsense-warnings.html
  • http://forums.sun.com/thread.jspa?threadID=635608

seem to discuss the same warning...

i guess @SuppressWarnings might be the key to happiness in that case


If you are really stuck up on avoiding the compiler warning, you can declare an interface in your test just for the purpose of avoiding it.

 interface MockGenericInterface extends GenericInterface<String> {}

Then you can do:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜