Fiz uma revisão de código para o meu colega há dois dias. Eu senti que não tinha uma boa compreensão dos genéricos do Java, então peguei o livro "Effective Java" 1 e depois olhei para os capítulos relevantes. No Item 24: Elimine avisos desmarcados, o autor usa o método Public <t> t [] ToArray (t [] a) na classe Arraylist como um exemplo para ilustrar como usar a annotação @suppresswarnings para variáveis.
Arraylist é uma classe genérica, que é declarada assim:
Javapublic Class ArrayList <E> estende a Lista de implementos abstrataList <E>
O método de ToArray (t [] a) desta classe é um método genérico, que é declarado e implementado assim:
@Suppresswarnings ("desmarcados") public <T> t [] ToArray (t [] a) {if (a.Length <size) // Faça uma nova matriz do tipo de tempo de execução de A, mas meu conteúdo: return (t [])) Arrays.copy (elementData, tamanho, A.GetClass ()); tamanho) a [tamanho] = nulo; retorna a;} Este método é realmente declarado na interface de coleta. Como costumamos usá -lo através do ArrayList, usaremos o ArrayList como exemplo aqui.
1 Por que é declarado como um tipo diferente?
Minha pergunta é: por que esse método usa o Tipo T em vez do Tipo E do Arraylist? Ou seja, por que esse método não é declarado assim:
Javapublic e [] ToArray (e [] a);
Se os tipos forem iguais, o erro do tipo de parâmetro poderá ser encontrado durante a compilação. Se os tipos forem diferentes, é fácil gerar erros de tempo de execução. Por exemplo, o seguinte código:
// Crie um ArrayListlist <String> strlist = new ArrayList <String> (); strlist.add ("abc"); strlist.add ("xyz"); // converte o strlist atual em uma matriz numérica. Observe que não há erros de compilação na declaração a seguir. Número [] numArray = strlist.toArray (novo número [0]); Execute o código acima e a linha 6 lançará uma exceção java.lang.arraystoreException.
Se o método ToArray usar o Tipo E, a instrução 2 gerará um erro de compilação. Os erros de compilação são mais amigáveis do que os erros de tempo de execução. Além disso, o principal objetivo dos genéricos é eliminar os erros de conversão do tipo (ClassCastException) durante a compilação. Este método é o oposto. Este é um grande bug? Eu encontrei um bug java, mas ainda não posso acreditar.
Depois de verificar a Internet, esse problema foi discutido muitas vezes 2, 3, 4.
2 pode melhorar a flexibilidade
Esta declaração é mais flexível e pode converter elementos na lista atual em uma matriz de tipos mais gerais. Por exemplo, o tipo de lista atual é inteiro e podemos converter seus elementos em uma matriz numérica.
List <Teger> intlist = new ArrayList <Teger> (); intlist.add (1); intlist.add (2); número [] numArray = intlist.toarray (novo número [0]);
Se esse método for declarado como tipo E, o código acima terá um erro de compilação. Parece que seria mais apropriado declarar o método da seguinte forma:
Javapublic <t super e> t [] toArray (t [] a);
No entanto, a sintaxe como <t super e> não existe em Java. E mesmo que exista, não funciona para matrizes. É também por esse motivo que, ao usar esse método, mesmo que T seja a classe pai de E, ou t, é o mesmo que e, java.lang.arraystoreException 5, 6, 7 não pode ser completamente evitado. Por favor, veja os dois códigos a seguir. No primeiro código, T é a classe pai de E e, no segundo código, T é o mesmo que E. Ambas as exceções de lançamento de código.
Código 1:
Lista <Teger> intlist = new ArrayList <Teger> (); intlist.add (1); intlist.add (2); Float [] floatArray = novo float [2]; // float é uma subclasse de número, então float [] é uma subclasse do número [] número [] numArray = floatArray; // A seguinte declaração lançará uma exceção ArrayStoreException numarray = intlist.toarray (numarray);
Código 2:
List <MumM> intlist = new ArrayList <Mumle> (); // O tipo de lista é o número. Mas o número é uma classe abstrata e só pode armazenar instâncias de sua subclasse intlist.add (new Integer ()); intlist.add (new Integer ()); Float [] floatArray = new float []; // float é uma subclasse de número, então float [] é uma subclasse do número [] número [] numArray = floatArray; // A seguinte declaração lançará uma exceção de ArrayStoreException numarray = intlist.ToArray (nUMArray);
As exceções acima são todas causadas por esse fato: se A é a classe pai de B, então A [] é a classe pai de B []. Todas as classes em Java herdam do objeto, e objeto [] é a classe pai de todas as matrizes.
Este post 8 dá um exemplo, mostrando que, mesmo que o tipo desse método seja declarado como E, a ArrayStoreException não pode ser evitada.
Esta exceção também é mencionada na documentação deste método:
ArrayStoreException se o tipo de tempo de execução da matriz especificado não for um supertipo do tipo de tempo de execução de todos os elementos nesta lista.
3 Pode ser compatível com versões antes do Java 1.5
Este método apareceu antes da introdução de genéricos em Java (os genéricos foram introduzidos no JDK1.5). Foi declarado naquele momento:
Javapublic Object [] ToArray (objeto [] a)
Depois que os genéricos aparecem, muitas classes e métodos se tornam genéricos. Este método também declara assim:
Javapublic <T> t [] ToArray (t [] a)
Esta declaração é compatível com as versões antes do Java 1.5.
4 mais algumas palavras
Este método requer um parâmetro de matriz. Se o comprimento desta matriz for maior ou igual ao tamanho da lista atual, os elementos da lista serão armazenados na matriz; Se o comprimento desta matriz for menor que o tamanho da lista atual, uma nova matriz será criada e os elementos na lista atual serão armazenados na matriz recém -criada. Para melhorar a eficiência, se possível, o comprimento da matriz passada deve ser maior ou igual ao tamanho da lista para evitar a criação de uma nova matriz por esse método.
List <Teger> intlist = new ArrayList <Teger> (); intlist.add (); intlist.add (); // colar em uma matriz, seu comprimento é número [] numArray = intlist.toArray (novo número []); // Colar // Colar em uma matriz, seu comprimento é igual ao comprimento do número intlist [] numArray = intlist.toArray (novo número [intlist.size ()]); //Declaração
Além disso, a matriz como parâmetros não pode ser nula, caso contrário, uma NullPointerException será lançada.
Notas de rodapé:
1
Java eficaz (2ª edição)
2
Link
3
Link
4
Link
5
Link
6
Link
7
Link
8
Link
9
Link
10
Link
Criado: 2016-04-06 Qua 21:14
EMACS 24.5.1 (Modo Org 8.2.10)
Validar
O conteúdo acima é a razão pela qual o tipo de parâmetro do método Java ArrayList.ToArray (t []) introduzido a você pelo editor é t em vez de E. Espero que seja útil para todos!