static method on child class with parametrized type

I have a Parent and a Child class:

Parent.java

import java.util.Arrays;
import java.util.List;

public class Parent {

  private final String name;

  public String getName() {
    return name;
  }

  public Parent(String name) {
    this.name = name;
  }

  static Parent calculate() {
    return new Parent("Parent");
  }

  static List<Parent> calculateList() {
    return Arrays.asList(new Parent("Father"), new Parent("Mother"));
  }
}

Child.Java

import java.util.Arrays;
import java.util.List;

public class Child extends Parent {

  public Child(String name) {
    super(name);
  }

  static Child calculate() {
    return new Child("Child");
  }

  static List<Child> calculateList() {
    return Arrays.asList(new Child("Brother"), new Child("Sister"));
  }
}

I get a "The return type is incompatible with Parent.calculateList() Java(67109268)", but in this case List<Parent> Parent.calculateList() is static, and so is List<Child> Child.calculateList() and the calculate() methods work as I would expect.

Changing method names or return types would solve this issue, but I’m interested in why this is happening with static non abstract class methods, have researched on forums, but haven’t found a solution.

>Solution :

That would be long but I’ll explain 🙂

First of all, in JLS, section 8.4.8, the following is specified:

A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:

Therefore, your method calculateList() is actually overridden by the Child. That’s right – the static method is inherited from Parent although it is bound to a class but not to an instance.

Thus, because you inherit it, by redeclaring it you actually override it (This is also stated in JLS). So you have to retain the signature and the return type (Which is not part of the signature btw).

Finally, you changed the return type from List<Parent> to List<Child>, but because in Java generics are invariant, List<Child> is NOT a subtype of List<Parent>. Therefore, you break the return type, thus you get the error.

So, by changing the name of the static method in Child, you no longer override an inherited calculateList(), therefore you do not cause any clash.

Hope it helped, have a nice day.

Leave a Reply