Incapaz de fazer referência estática para subclasse genérica (Java)
-
21-08-2019 - |
Pergunta
Eu tenho o seguinte código:
class SuperClass {
public static String getName() { return "super"; }
}
class SubClass extends SuperClass {
public static String getName() { return "sub"; }
}
public class Dummy<T extends SuperClass> {
public void print() {
System.out.println("SuperClass: " + SuperClass.getName());
System.out.println("SubClass: " + SubClass.getName());
System.out.println("T: " + T.getName());
}
public static void main(String[] args) {
new Dummy<SubClass>().print();
}
}
Este código gera o seguinte:
SuperClass: super
SubClass: sub
T: super
A minha pergunta é: Por que não T.getName () retornar o valor de SubClass.getName ()? Afinal, eu especificado que T == subclasse. Ou função estática chama inválido para referências genéricas?
Muito obrigado antecipadamente!
Solução
Este não é apenas uma questão sobre os genéricos.
Se você diz:
SuperClass obj = new SubClass();
System.out.println(obj.getName());
Você também terá "super". Não há métodos estáticos "polimórficas".
No seu caso, tudo o compilador sabe sobre T
é que ele estende SuperClass
, por isso vai chamar SuperClass.getName()
.
Outras dicas
Ao contrário de modelos C ++, trabalho Java genéricos por tipo apagamento, por isso só gera uma classe para todos os valores de T
, e traduz todas as referências para digitar T
nesta classe para o super tipo de T
, neste caso SuperClass
, em seguida, utiliza expedição virtual para fornecer a variância para chamadas para métodos de objetos, e expedição estática para chamadas para métodos estáticos.
Então, quando você faz Dummy<SubClass>.print()
, o compilador não faz uma substituição global de T
com SubClass
em Dummy
. Tudo o compilador faz é verificar se os usos de T
como um argumento ou tipo de retorno dos métodos de Dummy
são SubClass
. Não há nenhuma alteração em qualquer código dentro Dummy
, de modo que o mesmo método SuperClass
estática é chamado o que quer T
é.
Se você quer um comportamento diferente em uma classe genérica, dependendo do tipo parametrizado, você tem passar um objeto desse tipo e usar um método virtual, ou passar na classe para o tipo ea utilização reflexão.
Quando você instanciated a classe com "nova Manequim ()" você chamou o construtor padrão que na verdade não definir nada. Quando o método de impressão foi chamado, a serra VM que o tipo de T, como declarado na declaração de classe, é SuperClass; Em seguida, chama o método estático em sua classe.