Features of generics in Java

Question:

Please read and understand the question carefully before answering. So we have this code, it will compile and there will be no errors:

public static void main(String[] args) {
    method(4,"s");
}

static <K> void method(K k1, K k2) {

}

I thought that there should be a logical error, well, if not, then such features of Java. Next, there is this code:

public static void main(String[] args) {
    method(new ArrayList<Executor>(), new Object());
}

static <K> void method(List<K> k, K k2) {

}

This code is already throwing a compilation error. The compiler says that I'm not putting in the method (List<Executor>, java.util.concurrent.Executor) what I need. Indeed, Object is not an Executor for you. But now my main question is why in the first case the compiler does not care that different data types are assigned to the same parameterized type, and in the second case the compiler calculates what the argument of the second method should be based on the first method argument. I don't understand what logic works in both cases.

And one more equally important question, if we slightly change the second code example like this:

public static void main(String[] args) {
    method(new ArrayList<Executor>(), 150);
}

static <K> void method(List<? extends K> k, K k2) {

}

Now no error occurs, and we can shove any data types and the compiler doesn't care! We just changed List<K> to List<? extends K> . At this point, I'm at a loss as to what that means. A leaf that contains something that inherits from К , but what is К ? And why in the end we are allowed to put anything in the method parameters (I remind you that in the previous example with a sheet this is not allowed).

Answer:

Bounds for parameters of parameterized types work a little differently than they do for simple types. In the first case, both types can be cast to Object, in the second case, the type can only be either Object or Executor. If a simple type can be easily "lowered" to an object, then generics in parameterized types don't allow that by default – unless you specify ? extends K , allowing the use of K's descendants, or ? super K , allowing the use of K's ancestors. In this case, you specified ? extends K , which allows you to use Object instead of K, so the method parameter list is formed as List<? extends Object>, Object .

I can be wrong about something, the exact answers to these questions are contained in the JLS (Java Language Specification)

Scroll to Top