Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected compiler warning for "<T extends ...>" return type

When I compile the following Java code (using Oracle JDK 1.7.0_25):

public class StackOverflowQuestion {

    interface Example {

        <T extends Example> T init();
    }

    static class ExampleImpl implements Example {

        @Override
        public ExampleImpl init() {
            return this;
        }
    }
}

I get a warning:

StackOverflowQuestion.java:11: warning: [unchecked] init()
  in ExampleImpl implements <T>init() in Example
        public ExampleImpl init() {
                           ^
  return type requires unchecked conversion from ExampleImpl to T
  where T is a type-variable:
    T extends Example declared in method <T>init()

I can't understand why it says "return type requires unchecked conversion" as the class implements Example so as far as I can see it's a valid return type.

Can anyone explain to me what's wrong?

like image 224
ᴇʟᴇvᴀтᴇ Avatar asked Apr 10 '26 15:04

ᴇʟᴇvᴀтᴇ


1 Answers

The generic method in Example is supposed to work where T can be any type extending Example, but you have tried to implement it in ExampleImpl in such a way that it always returns an ExampleImpl. This may be ok if ExampleImpl is the only class implementing Example, but if there are others you can get a ClassCastException at runtime.

In the following example, we instantiate a new ExampleImpl, cast it to the base interface and then call the generic method init() with T equal to ExampleImpl2. This is supposed to return an ExampleImpl2, but since you returned this, it throws a ClassCastException. This is why your code must generate a warning.

public class StackOverflowQuestion {

    interface Example {

        <T extends Example> T init();
    }

    static class ExampleImpl implements Example {

        @Override
        public ExampleImpl init() {
            return this;
        }
    }

    static class ExampleImpl2 implements Example {

        @Override
        public <T extends Example> T init() {
            return null;
        }
    }

    public static void main(String[] args) {
        ExampleImpl2 e2 = ((Example) new ExampleImpl()).<ExampleImpl2>init();
    }
}
like image 173
Paul Boddington Avatar answered Apr 12 '26 04:04

Paul Boddington



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!