Herança de classe abstrata com um método estático

Achei esse exemplo na Internet e gostaria de saber porquê ao rodar o programa ele imprime Writing e não Writing Code?

abstract class Writer {
public static void write() {
System.out.println(“Writing…”);
}
}

class Author extends Writer {
public static void write() {
System.out.println(“Writing book”);
}
}

public class Programmer extends Writer {
public static void write() {
System.out.println(“Writing code”);
}

public static void main(String[] args) {
	Writer w = new Programmer();
	w.write();
}

}

Então ele deveria imprimir o que está definido no método write em Programmer que não é o caso.

Métodos statics são da classe e não do objeto:

abstract class Writer {
 public static void write() {
  System.out.println("Writing…");
 }
 public static void writeChar(char c) {
  System.out.println("Writing… " + c);
 }
}
class Author extends Writer {
 public static void write() {
  System.out.println("Writing book");
 }
}
public class Programmer extends Writer {
 public static void write() {
  System.out.println("Writing code");
 }
 public static void main(String[] args) {
  Writer w = new Programmer();
  w.write(); // Writing… (da classe Writer, pois w é do tipo Writer)
  Programmer p = (Programmer) w;
  p.write(); // Writing code (da classe Programmer, pois p é do tipo Programmer)
  p.writeChar('A'); // Writing… A (da classe Writer, pois Programmer não tem esse método)
 }
}

Se os métodos não fossem statics a saída seria:

Writing code
Writing code
Writing… A

O comportamento difere entre métodos de classe e métodos de instancia.

É dito que um método de instancia é sobreescrito (overriding) enquanto que um método de classe é apenas escondido (hiding).

Você pode ler mais detalhes aqui:

https://docs.oracle.com/javase/tutorial/java/IandI/override.html

E aqui:

https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#jls-8.4.8

Mas em resumo:

  • Um método de classe é invocado com base no tipo da variável que o contém.
  • Um método de intancia é invocado com base no tipo do objeto instanciado nesta variável.

Sendo assim:

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}

class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;

        myAnimal.testClassMethod();         // "The static method in Animal"
        myAnimal.testInstanceMethod();      // "The instance method in Cat"
        // Para invocar o estático de Cat, só com casting
        ((Cat) myAnimal).testClassMethod(); // "The static method in Cat"
    }
}

De qualquer forma, é recomendado que ao acessar métodos estáticos, use o nome da classe e não do objeto. Ou seja:

Writer.write();
// ou
Programmer.write();

Ao invés de:

new Writer().write();
// ou
new Programmer().write();

Obs: Ao postar código, utilize as tags corretas para melhor visualização de todos. Em caso de duvidas, este tópico pode ajudar.