Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can unchecked warnings be avoided when overriding a method with raw type parameters?

I am extending a class defined in a library which I cannot change:

public class Parent
{
    public void init(Map properties) { ... }
}

If I am defining a class 'Child' that extends Parent and I am using Java 6 with generics, what is the best way to override the init method without getting unchecked warnings?

public class Child extends Parent
{
    // warning: Map is a raw type. References to generic type Map<K,V> should be parameterized
    public void init(Map properties) { }
}

If I add generic parameters, I get:

   // error: The method init(Map<Object,Object>) of type Child has the same erasure as init(Map) of type Parent but does not override it
   public void init(Map<Object,Object>) { ... }
   // same error
   public void init(Map<? extends Object,? extends Object>) { ... }
   // same error
   public void init(Map<?,?>) { ... }

This error occurs regardless of whether I use a specific type, a bounded wildcard, or an unbounded wildcard. Is there a correct or idiomatic way to override a non-generic method without warnings, and without using @SuppressWarnings("unchecked")?

like image 410
sk. Avatar asked Oct 27 '08 22:10

sk.


People also ask

What are unchecked warnings?

An unchecked warning tells a programmer that a cast may cause a program to throw an exception somewhere else. Suppressing the warning with @SuppressWarnings("unchecked") tells the compiler that the programmer believes the code to be safe and won't cause unexpected exceptions.

How do you suppress a warning in Java?

Use of @SuppressWarnings is to suppress or ignore warnings coming from the compiler, i.e., the compiler will ignore warnings if any for that piece of code. 1. @SuppressWarnings("unchecked") public class Calculator { } - Here, it will ignore all unchecked warnings coming from that class.

Why is a raw type unsafe?

The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime. Therefore, you should avoid using raw types. The Type Erasure section has more information on how the Java compiler uses raw types.


2 Answers

Yes, you have to declare the overriding method with the same signature as in the parent class, without adding any generics info.

I think your best bet is to add the @SuppressWarnings("unchecked") annotation to the raw-type parameter, not the method, so you won't squelch other generics warnings you might have in your own code.

like image 140
Dov Wasserman Avatar answered Sep 19 '22 12:09

Dov Wasserman


Short answer: no way to do that.

Unsatisfying answer: disable the (specific) warnings in your IDE/build.xml.

If you cannot change the library, alas, you have to stick with non-generic methods.

The problem is that, despite after type erasure both init() have the same signature, they may in fact be different methods -- or the same(*). Compiler cannot tell should it do override or overload, so it's prohibited.

(*) Suppose the library developer meant init(Map<String,Integer>). Now you are implementing init(Map<String,String>). This is overloading, and two methods should exist in the vtable of Child class.

But what if the library developer meant init(Map<String,String>)? Then it's overriding, and your method should replace original init in Child class, and there would be only one method in the vtable of Child.

P.S. I hate how Generics implemented in Java :-(

like image 24
Vladimir Dyuzhev Avatar answered Sep 17 '22 12:09

Vladimir Dyuzhev