Nenhuma exceção durante a conversão de tipo com um nulo em java


Respostas:


323

Você pode converter nullpara qualquer tipo de referência sem obter nenhuma exceção.

O printlnmétodo não lança ponteiro nulo porque primeiro verifica se o objeto é nulo ou não. Se nulo, simplesmente imprime a string "null". Caso contrário, ele chamará o toStringmétodo desse objeto.

Adicionando mais detalhes: Os métodos de impressão interna chamam o String.valueOf(object)método no objeto de entrada. E, no valueOfmétodo, essa verificação ajuda a evitar a exceção de ponteiro nulo:

return (obj == null) ? "null" : obj.toString();

Para o resto da sua confusão, chamar qualquer método em um objeto nulo deve gerar uma exceção de ponteiro nulo, se não for um caso especial.


1
@JunedAhsan que casos especiais levariam a não lançar um NPE?
Holloway

@Trengot Verifique uma mencionada na resposta de Peter abaixo.
precisa

144

Você pode converter nullpara qualquer tipo de referência. Você também pode chamar métodos que manipulam a nullcomo argumento, por exemplo System.out.println(Object), mas não pode fazer referência a um nullvalor e chamar um método nele.

BTW Há uma situação complicada em que parece que você pode chamar métodos estáticos em nullvalores.

Thread t = null;
t.yield(); // Calls static method Thread.yield() so this runs fine.

12
Uau. Se solicitado, eu teria 100% de certeza de que isso lançaria uma exceção. Um caso complicado, de fato.
Magnilex

2
@Magnilex: Absolutamente! essa é uma pergunta típica do truque do exame OCPJP.
Ccpizza 17/03/16

3
Não é porque o compilador no bytecode "otimiza" para t.yield() -> Thread.yeld() assim mesmo? Semelhante a como final int i = 1; while (i == 1)é otimizado parawhile(true)
SGal

@SGal É ainda melhor porque a segunda otimização é AFAIK não obrigatória, enquanto a primeira é.
Paul Stelian

36

Isso é por design. Você pode converter nullpara qualquer tipo de referência. Caso contrário, você não seria capaz de atribuí-lo a variáveis ​​de referência.


obrigado! Esta observação sobre a atribuição de nulo a variáveis ​​de referência é realmente útil!
Max

22

A conversão de valores nulos é necessária para a construção a seguir, em que um método está sobrecarregado e se nulo é passado para esses métodos sobrecarregados, o compilador não sabe como esclarecer a ambiguidade, portanto, precisamos tipular nulo nesses casos:

class A {
  public void foo(Long l) {
    // do something with l
  }
  public void foo(String s) {
    // do something with s      
  }
}
new A().foo((String)null);
new A().foo((Long)null);

Caso contrário, você não poderá chamar o método necessário.


Na maioria dos casos, a conversão é implícita, por exemplo, String bar = null;lança o nullvalor para String. Até o momento, tive apenas que converter nulo explicitamente em um teste em que um método estava sobrecarregado e queria testar seu comportamento com entrada nula. Ainda assim, é bom saber que eu estava prestes a escrever uma resposta semelhante antes de encontrar a sua.
Vlasec

Curiosidade: l instanceof Longe s instanceof Stringretornará falsenesses casos.
Attila Tanyi

7

Println(Object) usa String.valueOf()

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

Print(String) faz verificação nula.

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}


3

Como outros escreveram, você pode converter nulo para tudo. Normalmente, você não precisa disso, pode escrever:

String nullString = null;

sem colocar o elenco lá.

Mas há ocasiões em que esses elencos fazem sentido:

a) se você deseja garantir que um método específico seja chamado, como:

void foo(String bar) {  ... }
void foo(Object bar) {  ... }

então faria diferença se você digitar

foo((String) null) vs. foo(null)

b) se você pretende usar seu IDE para gerar código; por exemplo, estou escrevendo testes de unidade como:

@Test(expected=NullPointerException.class)
public testCtorWithNullWhatever() {
    new MyClassUnderTest((Whatever) null);
}

Eu estou fazendo TDD; isso significa que a classe "MyClassUnderTest" provavelmente ainda não existe. Ao escrever esse código, posso usar meu IDE para gerar primeiro a nova classe; e, em seguida, gerar um construtor aceitando um argumento "Whatever" "pronto para uso" - o IDE pode descobrir, pelo meu teste, que o construtor deve usar exatamente um argumento do tipo Whatever.


2

Impressão :

Imprima um objeto. A sequência produzida pelo método String.valueOf (Object) é convertida em bytes

ValorDe :

se o argumento for nulo, uma sequência igual a "nulo"; caso contrário, o valor de obj.toString () é retornado.

Ele simplesmente retornará uma string com o valor "null" quando o objeto estiver null.


2

Isso é muito útil ao usar um método que seria ambíguo. Por exemplo: JDialog possui construtores com as seguintes assinaturas:

JDialog(Frame, String, boolean, GraphicsConfiguration)
JDialog(Dialog, String, boolean, GraphicsConfiguration)

Preciso usar esse construtor, porque quero definir o GraphicsConfiguration, mas não tenho pai para esse diálogo, portanto, o primeiro argumento deve ser nulo. Usando

JDialog(null, String, boolean, Graphicsconfiguration) 

é ambíguo, portanto, neste caso, posso restringir a chamada convertendo nulo para um dos tipos suportados:

JDialog((Frame) null, String, boolean, GraphicsConfiguration)

0

Esse recurso de idioma é conveniente nessa situação.

public String getName() {
  return (String) memberHashMap.get("Name");
}

Se memberHashMap.get ("Name") retornar nulo, você ainda desejará que o método acima retorne nulo sem gerar uma exceção. Não importa qual seja a classe, null é null.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.