Pergunta

Eu estou estendendo uma classe definida em uma biblioteca que eu não posso mudar:

public class Parent
{
    public void init(Map properties) { ... }
}

Se eu estou definindo uma classe 'Criança' que se estende Pai e eu estou usando Java 6 com os genéricos, o que é a melhor maneira de substituir o método init sem receber avisos desmarcada?

public class Child extends Parent
{
    // warning: Map is a raw type. References to generic type Map<K,V> should be parameterized
    public void init(Map properties) { }
}

Se eu adicionar parâmetros genéricos, eu recebo:

   // error: The method init(Map<Object,Object>) of type Child has the same erasure as init(Map) of type Parent but does not override it
   public void init(Map<Object,Object>) { ... }
   // same error
   public void init(Map<? extends Object,? extends Object>) { ... }
   // same error
   public void init(Map<?,?>) { ... }

Este erro ocorre independentemente de eu usar um tipo específico, um wildcard delimitado, ou um curinga sem limites. Existe uma maneira correta ou idiomática para substituir um método não-genérico sem avisos, e sem utilizar @SuppressWarnings ( "unchecked")?

Foi útil?

Solução

Sim, você tem que declarar o método de substituição com a mesma assinatura como na classe pai, sem acrescentar qualquer informação genéricos.

Eu acho que sua melhor aposta é para adicionar a anotação @SuppressWarnings("unchecked") ao parâmetro do tipo cru, não o método, então você não vai silenciador outros genéricos avisos que você pode ter em seu próprio código.

Outras dicas

Resposta curta: Não. Maneira de fazer isso

resposta insatisfatórias: desativar o (específico) advertências em seu IDE / build.xml

.

Se você não pode mudar a biblioteca, infelizmente, você tem que ficar com métodos não-genéricos.

O problema é que, apesar após eliminação de tipo tanto init () têm a mesma assinatura, eles podem de fato ser diferentes métodos - ou a mesma (*). Compiler não pode dizer deveria fazer override ou sobrecarga, por isso é proibido.

(*) Suponha init desenvolvedor biblioteca significava (Map ). Agora você está implementando init (Map ). Esta é a sobrecarga, e dois métodos deve existir no vtable de classe Child.

Mas e se o desenvolvedor biblioteca significava init (Map )? Então é substituir, e seu método deve substituir o init original na classe Child, e não haveria apenas um método no vtable da criança.

P.S. Eu odeio como genéricos implementado em Java: - (

Eu acho resposta acima quis dizer @SuppressWarnings ( "rawtypes") em vez.

Você tem que declarar o método com a mesma assinatura como o pai, e, portanto, você receberá avisos quando compilar. Você pode suprimi-los com @SuppressWarnings ( "unchecked")

A razão pela qual não há nenhuma maneira de se livrar desta situação é que os avisos estão lá para que você saiba que é possível criar coleções com tipos inválidos neles. Os avisos só deve ir embora quando todo o código que poderia permitir que foi removido. Desde que você está herdando de uma classe não-genérico sempre será possível criar uma coleção com conteúdos inválidos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top