O seguinte é exibido a todos para cada mal -entendido.
1. Uso excessivo de Null
Evitar o uso excessivo de nulo é a melhor prática. Por exemplo, uma abordagem melhor é fazer com que o método retorne à matriz ou coleção vazia em vez do valor nulo, porque isso pode impedir que o programa jogue NullPointerException. O seguinte fragmento de código receberá uma coleção de outro método:
List <String> AccountIds = Person.getAccountIds ();
Quando uma figura não possui uma conta, o getAccountIds () retornará o valor nulo e o programa jogará fora a exceção do NullPointerException. Portanto, é necessário ingressar na verificação do ar para resolver esse problema. Se você substituir o valor nulo retornado por uma lista vazia, o NullPointerException não aparecerá. Além disso, como não precisamos mais fazer uma curta verificação do Variable AccountId, o código se tornará mais conciso.
Quando você deseja evitar valores nulos, diferentes cenários podem levar práticas diferentes. Um método é usar o tipo opcional, que pode ser um objeto vazio ou um pacote de alguns valores.
Opcional <string> opcionalString = opcional.ofnullable (NulledString);
De fato, o Java8 fornece uma maneira mais concisa:
Opcional <string> opcionalString = opcional.ofnullable (NullialString);
O Java apoiou o tipo opcional da versão Java8, mas tem sido amplamente conhecido no mundo da programação funcional. Antes disso, foi usado na versão inicial do Java no Google Guava.
2. Ignore anormalidades
Muitas vezes ignoramos anormalidades. No entanto, a melhor prática é lidar com eles para iniciantes e programadores Java experientes. O arremesso anormal é geralmente proposital; portanto, na maioria dos casos, é necessário registrar eventos que causam anormalidades. Não subestime esse assunto. Pelo menos, para que outros desenvolvedores saibam a causa e o efeito, você deve explicar por que essas anormalidades não foram tratadas.
Selfie = Person.Shootaselfie ();
Uma maneira simples de enfatizar um certo sem importância é usar essas informações como um nome de variável anormal, assim:
Copie o código do código da seguinte forma:
tente {selfie.delete ();} catch (nullpointterException inalpporttant) {}
3. Modifique anormalidades simultaneamente
Essa anormalidade ocorre no objeto de coleta e, ao mesmo tempo, não usa o método fornecido pelo objeto Iterador para atualizar o conteúdo na coleção. Por exemplo, há uma lista de chapéus aqui e você deseja excluir todos os valores que contêm retalhos de orelha:
Lista <ihats = novo Arraylist <> (); hasarearflaps ()) {hats.remove (hat);}}
Se esse código for executado, o ConcurrentModificationException será lançado, porque o código o modificará enquanto atravessa esta coleção. Quando vários processos atuam na mesma lista, quando um dos processos atravessa a lista, o outro processo tenta modificar o conteúdo da lista e as mesmas anormalidades também podem ocorrer.
É muito comum no conteúdo de coleta de modificação simultânea com vários threads; portanto, é necessário usar o método comumente usado na programação simultânea, como bloqueios síncronos, conjuntos especiais para modificação simultânea e assim por diante. O Java resolve esse problema em um único thread e situação multi -thread.
Colete objetos e exclua -os em outro ciclo
A solução direta é colocar chapéus com retalhos de orelha em uma lista e excluí -la com outro ciclo. No entanto, isso requer um conjunto adicional para armazenar chapéus a serem excluídos.
List <ihatstoremove = new LinkedList <> ();
Use o método iterator.remove
Este método é mais simples e, ao mesmo tempo, não precisa criar uma coleção adicional:
Iterador <ihatitrator = hats.iterator ();
O método de usar listiterator
Quando a coleção da coleção da interface da lista é implementada, o iterador da lista é uma escolha muito adequada. O iterador que implementa a interface do listitorador não apenas suporta operações de exclusão, mas também suporta operações de adição e set. A interface ListoTrator implementa a interface do iterador; portanto, este exemplo é semelhante ao método de remoção do iterador. A única diferença é o tipo de iterador de chapéu e obtemos o método do iterador -usando o método listtrator (). Os seguintes fragmentos mostram como usar o método listerator.remove e listtrator.add para substituir o chapéu de abas de ouvido por Som <ombreros.
Ihat Sombro = novo Sombro (); ;
Usando o listiterator, o método Remow Remover e Adicionar pode ser substituído para chamar apenas um método de conjunto:
Ihat Sombro = novo Sombro (); );
Use o método de fluxo em Java 8
No Java8, os desenvolvedores podem converter uma coleção em fluxo e fluxo de filtro de acordo com algumas condições. Este exemplo informa como o filtro da API do fluxo chapé e evita a concorrente ModificationException. Hats = hats.stream ().
Copie o código do código da seguinte forma:
.Collect (Collectors.Tocollection (ArrayList :: New));
O método de coleta.Tocollection criará uma nova lista de Array, responsável por armazenar o valor dos chapéus filtrados. Se as condições de filtragem forem filtradas em um grande número de entradas, uma grande lista será gerada aqui. Portanto, você precisa usá -lo com cautela.
Use o método List.Removeif em Java 8
Você pode usar outro método mais conciso e claro no método Java 8 -Removeif:
Copie o código do código da seguinte forma:
Hats.removeif (ihat :: hasarflaps);
Na parte inferior, ele usa o iterator.remove para concluir esta operação.
Use uma coleção especial
Se você decidir usar copywriteArraylist em vez de Arraylist no início, não haverá problema. Como o copywonwritearraylist fornece métodos modificados (como definir, adicionar, remover), ele não alterará a matriz de coleta original, mas cria uma nova versão modificada. Isso permite que o Traversal modifique a versão original, para que a concorrente ModificationException não seja expulsa. As desvantagens desta coleção também são muito óbvias -uma nova coleção é gerada para cada modificação.
Existem outros conjuntos adequados para diferentes cenários, como copywriteset e concorrente.
Em relação a outro erro que pode ocorrer durante as modificações simultâneas, ele cria um fluxo de uma coleção. O critério geral para o fluxo é evitar a modificação da coleção de traseiro ao fazer a verificação do fluxo. O próximo exemplo mostrará como lidar adequadamente com o fluxo:
Lista <ihat> arquivadohats = hats.stream ().
O método Peek coleta todos os elementos e executa ações estabelecidas para cada elemento. Aqui, a ação é tentar excluir dados de uma lista básica, que está obviamente errada. Para evitar essas operações, você pode tentar alguns métodos explicados acima.
4. Defesa
Às vezes, para melhor colaborar, o código fornecido pela biblioteca padrão ou terceiros deve cumprir as dependências comuns. Por exemplo, é necessário cumprir o contrato conjunto entre o HashCode e o igual para garantir que uma série de classes de coleta na estrutura de coleta Java e outras classes usando os métodos HashCode e Iguals possam funcionar normalmente. Não cumpra erros, como exceção ou compilação de código de destruição;
O código de erro pode entrar no ambiente de produção, causando muitos efeitos adversos. Isso inclui pouca experiência na interface do usuário, relatórios de dados incorretos, desempenho ruim do aplicativo, perda de dados ou mais. Felizmente, esses erros catastróficos não ocorrem com frequência. O HashCode e os iguais foram mencionados antes que a cena que parece ser: a coleção depende do alvo para comparar os objetos ou se comparar, assim como o hashmap e o hashset. Em termos simples, existem dois critérios para este Contrato:
Se os dois objetos forem iguais, o código de hash deverá ser igual.
Se os dois objetos tiverem o mesmo código de hash, eles podem ser iguais ou diferentes.
O primeiro critério para destruição, quando você tenta recuperar dados de um hashmap, isso causará erros. O segundo critério significa que objetos com o mesmo código de hash não são necessariamente iguais.
Vamos dar uma olhada nas consequências de destruir o primeiro critério:
Public Static Boat {Nome da String Private; getClass ()! int hashcode () {return (int) (math.random () * 5000);}}
Como você pode ver, a classe de barco reescreve os métodos iguais e hashcode. No entanto, destruiu o contrato porque o HashCode retornou o valor aleatório para o mesmo objeto para cada chamada. É provável que o código a seguir não encontre um barco chamado Enterprise em Hashset, embora de fato tenhamos adicionado esse tipo de barco com antecedência:
Public static void main (string [] args) {set <arch> barcos = novo hashset <> (); (New Boat ("Enterprise"));};}
Outro acordo é o método finalizado. Aqui está uma referência ao documento Java oficial sobre sua descrição funcional:
O contrato convencional da Finalize é: quando a máquina virtual Javatm determina que qualquer encadeamento não pode mais acessar o objeto especificado de forma alguma, esse método será chamado. O método Finalize possui várias funções, incluindo o uso desse objeto para estar disponível para outros threads novamente; Por exemplo, o método Finalize que indica o objeto de conexão de entrada/saída pode executar a transação explícita de E/S para interromper a conexão antes do objeto descartado permanente.
Você pode decidir usar o método Finalize em um processador de arquivo para liberar recursos, mas esse uso é ruim. Como é chamado durante a reciclagem de lixo e o tempo do GC não tem certeza, o tempo para finalizar não será garantido.
5. Use o tipo original em vez de parametrização
De acordo com a descrição do documento Java: o tipo original não é parametizado, ou um membro não -estatal da RM (também não -herdância da interface pai ou pai). Antes de introduzir o tipo genérico Java, não havia tipo alternativo primitivo. O Java apoiou a programação genérica da versão 1.5 e não há dúvida de que essa é uma melhoria importante da função. No entanto, devido à compatibilidade com versões anteriores, há uma armadilha aqui que pode destruir todo o sistema de tipos. Lute o exemplo:
ListOfnumbers = novo ArrayList ();
Esta é uma lista de números definidos como o ArrayList original. Como não especifica os parâmetros de tipo, ele pode adicionar qualquer objeto a ele. No entanto, a última linha mapeia os elementos que ela contém para o tipo int e multiplicada por 2, imprimiu os dados após o dobro dos dados para a saída padrão.
Esse código não cometerá um erro durante a compilação, mas, uma vez executado, ele apresentará um erro quando estiver em execução, porque está tentando mapear o tipo de caractere para cirurgia plástica. Obviamente, se as informações necessárias estiverem ocultas, o sistema de tipos não ajudará a escrever um código de segurança.
Para resolver esse problema, você precisa especificar o tipo específico para os objetos da coleção:
Lista <Teger> ListOfnumbers = novo Arraylist <() ();
A única diferença em relação ao código anterior é a linha que define a coleção:
Copie o código do código da seguinte forma:
Lista <Teger> listOfnumbers = new ArrayList <();
A compilação de código modificada não pode ser passada porque está tentando adicionar uma string à coleta de plástico de armazenamento esperado. O compilador exibirá uma mensagem de erro e apontará para a linha que adiciona vinte caracteres à lista. O tipo genérico de parametrização é uma boa ideia. Nesse caso, o compilador pode verificar os tipos possíveis, para que a chance anormal de tempo de execução devido a inconsistências seja bastante reduzida.
O principal resumo dos cinco programadores de Java acima cometem erros, espero que todos possam gostar.