Search code examples
javagenericswildcardtype-parameter

Why I must declare type parameter before return type in Java?


Without any introduction to generics, I will post my question straight away. Why is this correct:

static<T extends Object> void m1(List<T> list){
        //some code
    }

And this is not (doesn't compile):

static void m2 (List<T extends Object> list){
        //some code
    }

Remember that we could use wildcards in the same approach, which would compile just fine:

static void m2 (List<? extends Object> list){
        //some code
    }

To sum up, why can we use wildcards declaration in parameters, while using type parameter we must declare it before return type?


Solution

  • There are two main points.

    First off, as @akuzminykh said in the comments to the question, the ? wildcard is basically just a way to tell the compiler "I don't know what this is gonna be, just assume it could be anything that derives from this class/interface, kthxbye". It doesn't declare any parameter that you could make use of within the method, no identifier you can call upon, nothing. However, type parameters do exactly that, and if you declare a new one, it's a different story than just "calling" the wildcard which you don't have to declare.

    Secondly, think of how you would declare a type parameter for a generic class. Do you think this would be enough?

    public class Foo {
        public T extends CharSequence getBar() {...}
    }
    
    public class Foo {
        public <T extends CharSequence> getBar() {...}
    }
    

    No, none of these two options would work. In order to use a generic type parameter within a class, you have to declare it along with the type itself, not along with the methods/fields that use them. Like this:

    public class Foo<T extends CharSequence> {
        public T getBar() {...}
    }
    

    And in order to use a generic type parameter within a method, you have to declare it along with the method itself or the type that contains the method, not along with the method parameters that use them.