Por que int num = Integer.getInteger (“123”) lança NullPointerException?

106

O seguinte código gera NullPointerException:

int num = Integer.getInteger("123");

Meu compilador está invocando getIntegerem null, pois é estático? Isso não faz sentido!

O que está acontecendo?

user282886
fonte
3
use Integer.getValue () em vez disso. Esta postagem do blog é uma boa explicação do porquê: konigsberg.blogspot.in/2008/04/…
Pranaysharma

Respostas:

212

A grande imagem

Existem dois problemas em jogo aqui:

  • Integer getInteger(String) não faz o que você pensa que faz
    • Ele retorna nullneste caso
  • a atribuição de Integerpara intcausa o desempacotamento automático
    • Uma vez que Integeré null, NullPointerExceptioné lançado

Para analisar (String) "123"a (int) 123, você pode usar por exemplo int Integer.parseInt(String).

Referências

Integer Referências API


Em Integer.getInteger

Aqui está o que a documentação tem a dizer sobre o que esse método faz:

public static Integer getInteger(String nm): Determina o valor inteiro da propriedade do sistema com o nome especificado. Se não houver nenhuma propriedade com o nome especificado, se o nome especificado estiver vazio ou null, ou se a propriedade não tiver o formato numérico correto, nullserá retornado.

Em outras palavras, esse método não tem nada a ver com a análise de a Stringpara um int/Integervalor, mas sim com o System.getPropertymétodo.

É certo que isso pode ser uma grande surpresa. É uma pena que a biblioteca tenha surpresas como essa, mas ela ensina uma lição valiosa: sempre consulte a documentação para confirmar o que um método faz.

Coincidentemente, uma variação desse problema foi apresentada em Return of the Puzzlers: Schlock and Awe (TS-5186) , apresentação de Josh Bloch e Neal Gafter na Sessão Técnica JavaOne 2009. Aqui está o slide de conclusão:

A moral

  • Métodos estranhos e terríveis se escondem nas bibliotecas
    • Alguns têm nomes que parecem inócuos
  • Se o seu código funcionar mal
    • Certifique-se de chamar os métodos corretos
    • Leia a documentação da biblioteca
  • Para designers de API
    • Não viole o princípio do menor espanto
    • Não viole a hierarquia de abstração
    • Não use nomes semelhantes para comportamentos totalmente diferentes

Para completar, também existem estes métodos que são análogos a Integer.getInteger:

Perguntas relacionadas


No autounboxing

A outra questão, claro, é como isso NullPointerExceptioné jogado. Para focar neste problema, podemos simplificar o snippet da seguinte maneira:

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!

Aqui está uma citação do Effective Java 2nd Edition, Item 49: Prefira tipos primitivos a primitivos em caixa:

Em resumo, use primitivos em vez de primitivos encaixotados sempre que você tiver escolha. Os tipos primitivos são mais simples e rápidos. Se você deve usar primitivas em caixa, tome cuidado! O autoboxing reduz a verbosidade, mas não o perigo, de usar primitivas em caixas. Quando seu programa compara duas primitivas em caixa com o ==operador, ele faz uma comparação de identidade, o que quase certamente não é o que você deseja. Quando seu programa faz cálculos de tipo misto envolvendo primitivos encaixotados e não encaixotados, ele faz o desempacotamento, e quando o seu programa faz o desempacotamento, ele pode lançar NullPointerException. Finalmente, quando seu programa encaixa valores primitivos, isso pode resultar em criações de objetos caras e desnecessárias.

Há lugares onde você não tem escolha a não ser usar primitivos in a box, por exemplo, genéricos, mas caso contrário, você deve considerar seriamente se a decisão de usar primitivos in a box é justificada.

Perguntas relacionadas

poligenelubrificantes
fonte
11
Então Integer.getInteger(s)é mais ou menos equivalente a Integer.parseInt(System.getProperty(s))? Acho que prefiro o segundo, embora seja mais detalhado, porque destaca o fato de que você está extraindo informações das propriedades do sistema.
MatrixFrog
5
Assim que postei esse comentário, percebi que poderia apenas olhar a fonte real da classe Inteiro! Eu estava no caminho certo, exceto que ele usa em Integer.decodevez de Integer.parseInt, que procura um líder 0xou 0para analisar o número como hexadecimal ou octal, respectivamente.
MatrixFrog
Para aqueles que estão perguntando por quê NullPointerException? : programmers.stackexchange.com/questions/158908/…
ROMANIA_engineer
2
@Oracle você pode descontinuar java.lang.Integer.getInteger (String), por favor?
mjaggard,
6

Verifique a documentação do método getInteger () . Neste método, o Stringparâmetro é uma propriedade do sistema que determina o valor inteiro da propriedade do sistema com o nome especificado. "123" não é o nome de nenhuma propriedade do sistema, conforme discutido aqui . Se você deseja converter esta String para int, use o método como int num = Integer.parseInt("123").

Sonal Patil
fonte