Pergunta

Se eu conseguir um NullPointerException em uma chamada como esta:

someObject.getSomething().getSomethingElse().
    getAnotherThing().getYetAnotherObject().getValue();

Eu recebo um texto de exceção bastante inútil como:

Exception in thread "main" java.lang.NullPointerException
at package.SomeClass.someMethod(SomeClass.java:12)

acho que é bastante difícil descobrir wich chamar nula realmente returend, muitas vezes encontrando-me refatoração do código para algo como isto:

Foo ret1 = someObject.getSomething();
Bar ret2 = ret1.getSomethingElse();
Baz ret3 = ret2.getAnotherThing();
Bam ret4 = ret3.getYetAnotherOject();
int ret5 = ret4.getValue();

e, em seguida, à espera de um NullPointerException mais descritivo que me diz qual a linha que procurar.

Alguns de vocês podem argumentar que concatening getters é ruim estilo e deve ser evitado de qualquer maneira, mas a minha pergunta é: Can I encontrar o bug sem alterar o código?

Dica:. Eu estou usando o eclipse e eu sei o que um depurador é, mas eu não posso figuere fora como aplicá-la para o problema

Minha conclusão sobre as respostas:
Algumas respostas me disse que eu não deveria getters cadeia um após o outro, algumas respostas mostrou o meu como depurar o meu código se eu disobayed esse conselho.

Eu aceitei uma resposta que me ensinou excactly quando getters cadeia:

  • Se eles não podem retornar nulo, encadeá-los enquanto você gosta. Não há necessidade de verificação! = Null, não há necessidade de se preocupar com NullPointerExceptions ( ser avisado de que o encadeamento ainda vialotes a lei de Deméter, mas eu posso viver com isso )
  • Se eles podem retornar null, não nunca, nunca encadeá-los e realizar uma verificação para valores nulos em cada um que pode retornar nulo

Isto faz algum conselho bom a depuração real inútil.

Foi útil?

Solução

A resposta depende de como você vê (o contrato) dos seus getters. Se eles podem retornar null você realmente deve verificar o valor de retorno de cada vez. Se o getter não deve retornar null, o getter deve conter um cheque e lançar uma exceção (IllegalStateException?) Ao invés de retornar null, que você nunca prometeu voltar. O stacktrace irá apontar-lhe o getter exato. Você pode até mesmo colocar o estado inesperado seu getter encontrada na mensagem de exceção.

Outras dicas

NPE é a exceção mais inútil Java, período. Parece estar sempre preguiçosamente implementado e nunca diz exatamente o que causou isso, mesmo tão simples como "x.y.z classe é nulo" ajudaria muito na depuração de tais casos.

De qualquer forma, a única boa maneira que eu encontrei para encontrar o atirador NPE nestes casos é o seguinte tipo de refatoração:

someObject.getSomething()
          .getSomethingElse()
          .getAnotherThing()
          .getYetAnotherObject()
          .getValue();

Lá você tem, agora NPE pontos para a linha correta e método assim correto, o que jogou a NPE real. Não como solução elegante como eu gostaria que fosse, mas funciona.

Em IntelliJ IDEA você pode definir exceptionbreakpoints . Aqueles fogo pontos de interrupção sempre que uma exceção especificada é acionada (você pode escopo a um pacote ou uma classe).

Dessa forma, ele deve ser fácil de encontrar a fonte de sua NPE.

Eu diria, que você pode fazer algo semelhante no netbeans ou eclipse.

EDIT: Aqui é uma explicação sobre como adicionar um exceptionbreakpoint em eclipse

Se você se encontra, muitas vezes escrevendo:

a.getB().getC().getD().getE();

este é provavelmente um cheiro de código e deve ser evitado. Você pode refatorar, por exemplo, em a.getE() que chama b.getE() que chama c.getE() que chama d.getE(). (Este exemplo pode não fazer sentido para o seu caso de uso particular, mas é um padrão para corrigir este cheiro de código.)

Veja também a Lei de Demeter , que diz:

  • Seu método pode chamar outros métodos em sua classe diretamente
  • Seu método pode chamar métodos em seus próprios campos diretamente (mas não em campos dos campos)
  • Quando o seu método usa parâmetros, o método pode chamar métodos sobre esses parâmetros diretamente.
  • Quando seu método cria objetos locais, esse método pode chamar métodos nos objetos locais.

Portanto, não se deve ter uma cadeia de mensagens, por exemplo, a.getB().getC().doSomething(). Seguindo essa "lei" tem muitos mais benefícios além de fazer NullPointerExceptions mais fácil de depurar.

Eu geralmente não acorrentam getters como este, onde há mais de um getter anulável.

Se você está funcionando dentro de sua ide você pode apenas definir um ponto de interrupção e usar a funcionalidade "avaliar a expressão" do seu ide em cada elemento sucessivamente.

Mas você vai estar coçando a cabeça no momento em que receber esta mensagem de erro a partir de seus registros do servidor de produção. Assim melhor manter um item anulável máximo por linha.

Enquanto isso, podemos sonhar com do Groovy operador de navegação segura

fracasso precoce também é uma opção.

Em qualquer lugar em seu código que um valor nulo pode ser retornado, considerar a introdução de um cheque de um valor nulo retorno.

public Foo getSomething()
{
  Foo result;
  ...
  if (result == null) {
    throw new IllegalStateException("Something is missing");
  }
  return result;
}

Veja como encontrar o erro, usando Eclipse.

Primeiro, defina um ponto de interrupção na linha:

someObject.getSomething().getSomethingElse().
getAnotherThing().getYetAnotherObject().getValue();

Executar o programa no modo de depuração, permitir que o depurador para passar a sua perspectiva quando a linha é hit.

Agora, destaque "someObject" e pressione CTRL + SHIFT + I (ou clique direito e dizer "inspecionar").

É nulo? Você encontrou seu NPE. É não-nulo? Em seguida, realce someObject.getSomething () (incluindo os parênteses) e inspecioná-lo. É nulo? Etc. Continue para baixo da cadeia para descobrir onde o seu NPE está ocorrendo, sem ter que alterar seu código.

Você pode querer referir-se a esta pergunta sobre como evitar! = Null .

Basicamente, se nula é uma resposta válida, você tem que verificar para ele. Se não, afirmá-la (se possível). Mas o que você faz, e tentar minimizar os casos em que nulo é uma resposta válida para este, entre outras razões.

Se você está tendo para chegar ao ponto onde você está dividindo-se a linha ou fazendo a depuração elaborado para detectar o problema, em seguida, que geralmente é a maneira de Deus de dizer-lhe que o seu código não está verificando o nulo cedo o suficiente .

Se você tem um método ou construtor que leva um parâmetro de objeto eo objeto / método em questão não pode sensatamente lidar com esse parâmetro sendo nula, em seguida, basta verificar e lançar uma NullPointerException lá e então.

Eu vi as pessoas inventam "estilo de codificação" regras para tentar contornar este problema, tais como "não é permitido mais de um ponto em uma linha". Mas isso só incentiva programação que pontos o bug no lugar errado.

expressões acorrentados como essa são uma dor de depuração para NullPointerExceptions (ea maioria dos outros problemas que podem ocorrer) para que eu aconselho-o a tentar evitá-lo. Você provavelmente já ouviu que, embora o suficiente e como um cartaz anterior mencionou você pode adicionar pontos de quebra no NullPointerException real para ver onde ele ocorreu.

Em eclipse (ea maioria dos IDEs), você também pode usar expressões de inspeção para avaliar o código em execução no depurador. Você pode fazer isso bu selecionando o código e usar o menu Contet para adicionar um novo relógio.

Se você está no controle do método que retorna nulo você também pode considerar o padrão Objeto Nulo se nulo é um valor válido para retorno.

Coloque cada getter em sua própria linha e depurar. Passar por cima (F6) cada método para descobrir qual retorna chamada nulo

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