Possible Bug in javac unchecked cast detection

Alex Buckley alex.buckley at oracle.com
Fri May 2 19:55:29 UTC 2014


If none of the interface declarations were generic, then the language 
would happily accept the cast from SubInterfaceA to SubInterfaceB; as 
JLS 5.5.1 says, "the cast is always legal at compile time (because even 
if T does not implement S, a subclass of T might)."

With generic declarations, the unchecked cast rules come into play, 
aiming to warn you if anything happens that could possibly lead to a 
ClassCastException at run time. These rules could have been smarter, to 
detect the common superinterface of SubInterfaceA<String> and 
SubInterfaceB<String>, but that decision was not taken in 1998.

Alex

On 5/2/2014 1:12 AM, Tom Schindl wrote:
> Hi Alex,
>
> Thanks for the confirmation. I'll file a bug against javac then. What I
> don't yet understand how one can fix such a situation without a warning
> or why JLS does not allow the cast.
>
> I can fix the unchecked warning with but then (if turned on in my
> Eclipse I get a warning about an unnecessary typecast - so do IntelliJ
> users)
>
> b = (SubInterfaceB<String>)(BaseInterface<String>)a;
>
> which of course is correct because one does not need to cast
> SubInterfaceA<T> to BaseInterface<T>. The only solution to work without
> any warning suppression is using an intermediate variable.
>
> BaseInterface<T> temp = a;
> b = (SubInterfaceB<String>)temp;
>
> what i don't fully grasp then why JLS does not directly allow me to cast
> from SubInterfaceA<T> to SubInterfaceB<T>.
>
> Tom
>
> On 01.05.14 20:41, Alex Buckley wrote:
>> Eclipse is right. Given the interface declarations below, a cast from
>> SubInterfaceA<String> to SubInterfaceB<String> is unchecked. By JLS
>> 5.5.2, an unchecked warning is due unless @SuppressWarnings is in
>> effect; lint mode doesn't matter.
>>
>> Alex
>>
>> On 5/1/2014 9:11 AM, Tom Schindl wrote:
>>> Hi,
>>>
>>> While cleaning up the javafx codebase (who has a lot of use of generics)
>>> I came across casts the eclipse java compiler marks as unchecked while
>>> javac -Xlint:all does not warn about.
>>>
>>> The following snippet shows gist of the problem:
>>>
>>>> package a;
>>>>
>>>> public class CastTest {
>>>>      public interface BaseInterface<T> {
>>>>
>>>>      }
>>>>
>>>>      public interface SubInterfaceA<T> extends BaseInterface<T> {
>>>>
>>>>      }
>>>>
>>>>      public interface SubInterfaceB<T> extends BaseInterface<T> {
>>>>
>>>>      }
>>>>
>>>>      public static void main(String[] args) {
>>>>          SubInterfaceA<String> a = null;
>>>>          SubInterfaceB<String> b = (SubInterfaceB<String>) a; // javac
>>>> does not warn
>>>>          b = (SubInterfaceB<String>)(BaseInterface<String>)a;
>>>>
>>>>      }
>>>> }
>>>
>>> I first thought of a bug in the eclipse compiler but they claim their
>>> compiler is correct because the spec says:
>>>
>>>
>>>> "A cast from a type S to a parameterized type (§4.5) T is unchecked
>>>>      unless at least one of the following is true:
>>>>      *  S <: T
>>>>      *  All of the type arguments (§4.5.1) of T are unbounded wildcards
>>>>      *  T <: S and S has no subtype X other than T where the type
>>>> arguments
>>>>         of X are not contained in the type arguments of T."
>>>
>>> So before fileing a bug and start fixing the javafx code I wanted to get
>>> feedback from the compiler gurus on this list who is right and who is
>>> wrong.
>>>
>>> Thanks
>>>
>>> Tom
>>>
>


More information about the compiler-dev mailing list