O que é nulo em Java?

252

O que é null?

É nulluma instância de alguma coisa?

A que conjunto nullpertence?

Como isso é representado na memória?

unj2
fonte
yegor256. Sobre nulo de JLS. "O literal nulo. O tipo nulo tem um valor, a referência nula, representada pelo literal nulo nulo, formado a partir de caracteres ASCII. Um literal nulo é sempre do tipo nulo." Sobre pontos no artigo. 'Objetos mutáveis ​​e incompletos' é um recurso. 'Slow Failing' é uma habilidade por design. 'Pensamento computacional versus pensamento objetal' são apenas duas maneiras de pensar. "Semântica ambígua" é muito subjetiva. 'Tratamento de erros ad-hoc' é outro tipo de trabalho com erros. Nulo é um literal ou qualquer outra coisa especificada no JLS, ao contrário de não ser bom ou ruim.
Oleksii Kyslytsyn

Respostas:

310

Null é uma instância de alguma coisa?

Não, não existe um tipo que nullseja um instanceof.

15.20.2 Operador de comparação de tipos instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

No tempo de execução, o resultado do instanceofoperador é truese o valor da RelationalExpression não for nulle a referência poderá ser convertida para o ReferenceType sem gerar a ClassCastException. Caso contrário, o resultado é false.

Isso significa que para qualquer tipo Ee R, para qualquer E o, onde o == null, o instanceof Ré sempre false.


A que conjunto pertence 'null'?

JLS 4.1 Os tipos de tipos e valores

Há também um tipo nulo especial , o tipo da expressão null, que não tem nome. Como o tipo nulo não tem nome, é impossível declarar uma variável do tipo nulo ou converter para o tipo nulo . A nullreferência é o único valor possível de uma expressão do tipo nulo . A nullreferência sempre pode ser convertida para qualquer tipo de referência. Na prática, o programador pode ignorar o tipo nulo e apenas fingir que nullé apenas um literal especial que pode ser de qualquer tipo de referência.


O que é nulo?

Como a citação JLS acima diz, na prática você pode simplesmente fingir que é "apenas um literal especial que pode ser de qualquer tipo de referência".

Em Java, null == null(isso nem sempre é o caso em outras linguagens). Observe também que, por contrato, ele também possui esta propriedade especial (de java.lang.Object):

public boolean equals(Object obj)

Para qualquer nullvalor que não seja de referência x, x.equals(null)deveria return false.

Também é o valor padrão (para variáveis ​​que os possuem) para todos os tipos de referência:

JLS 4.12.5 Valores iniciais das variáveis

  • Cada variável de classe, variável de instância ou componente de matriz é inicializado com um valor padrão quando é criado:
    • Para todos os tipos de referência, o valor padrão é null.

Como isso é usado varia. Você pode usá-lo para ativar o que é chamado de inicialização lenta de campos, onde um campo teria seu valor inicial nullaté que seja realmente usado, onde será substituído pelo valor "real" (que pode ser caro para calcular).

Existem também outros usos. Vamos dar um exemplo real de java.lang.System:

public static Console console()

Retorna : o console do sistema, se houver, caso contrário null.

Este é um padrão de uso muito comum: nullé usado para denotar a inexistência de um objeto.

Aqui está outro exemplo de uso, desta vez de java.io.BufferedReader:

public String readLine() throws IOException

Retorna : A que Stringcontém o conteúdo da linha, sem incluir nenhum caractere de terminação de linha ou nullse o final do fluxo foi atingido.

Então, aqui, readLine()retornaria instanceof Stringpara cada linha, até que finalmente retorne a nullpara significar o fim. Isso permite que você processe cada linha da seguinte maneira:

String line;
while ((line = reader.readLine()) != null) {
   process(line);
}

Pode-se projetar a API para que a condição de terminação não dependa do readLine()retorno null, mas pode-se ver que esse design tem o benefício de tornar as coisas concisas. Observe que não há problema com linhas vazias, porque uma linha vazia "" != null.

Vamos dar outro exemplo, desta vez de java.util.Map<K,V>:

V get(Object key)

Retorna o valor para o qual a chave especificada está mapeada ou nullse este mapa não contiver mapeamento para a chave.

Se este mapa permitir nullvalores, um valor de retorno nullnão indica necessariamente que o mapa não contém mapeamento para a chave; também é possível que o mapa mapeie explicitamente a chave null. A containsKeyoperação pode ser usada para distinguir esses dois casos.

Aqui começamos a ver como o uso nullpode complicar as coisas. A primeira instrução diz que, se a chave não estiver mapeada, nullserá retornada. A segunda declaração diz que, mesmo que a chave esteja mapeada, ela tambémnull pode ser retornada.

Por outro lado, java.util.Hashtablesimplifica as coisas, não permitindo nullchaves e valores; isso V get(Object key), se retornar null, significa sem ambiguidade que a chave não está mapeada.

Você pode ler o restante das APIs e descobrir onde e como nullé usado. Lembre-se de que eles nem sempre são os exemplos de melhores práticas .

De um modo geral, nullsão usados ​​como um valor especial para significar:

  • Estado não inicializado
  • Condição de rescisão
  • Objeto inexistente
  • Um valor desconhecido

Como isso é representado na memória?

Em Java? Não é da sua conta. E é melhor mantê-lo assim.


É nulluma coisa boa?

Agora isso é subjetivo limítrofe. Algumas pessoas dizem que isso nullcausa muitos erros de programador que poderiam ter sido evitados. Alguns dizem que em uma linguagem que pega NullPointerExceptioncomo Java, é bom usá-lo porque você irá falhar rapidamente em erros de programador. Algumas pessoas evitam nullusar o padrão de objeto Nulo , etc.

Este é um tópico enorme por si só, por isso é melhor discutido como resposta a outra pergunta.

Terminarei isso com uma citação do próprio inventor null, CAR Hoare (de fama de quicksort):

Eu chamo de erro do meu bilhão de dólares. Foi a invenção da nullreferência em 1965. Naquela época, eu estava projetando o primeiro sistema abrangente de tipos para referências em uma linguagem orientada a objetos (ALGOL W). Meu objetivo era garantir que todo o uso de referências fosse absolutamente seguro, com a verificação realizada automaticamente pelo compilador. Mas não pude resistir à tentação de fazer uma nullreferência, simplesmente porque era muito fácil de implementar. Isso levou a inúmeros erros, vulnerabilidades e falhas no sistema, que provavelmente causaram um bilhão de dólares de dor e danos nos últimos quarenta anos.

O vídeo desta apresentação é mais profundo; é um relógio recomendado.

poligenelubricants
fonte
4
Referências nulas existiam no LISP (as NIL) em 1960, e provavelmente antes. Mas não acho que Hoare esteja realmente tentando reivindicar a invenção de referências nulas nessa citação.
Stephen C
7
Hoare não está tentando reivindicar a invenção de referências nulas; ele está apenas afirmando que os disponibilizou em um local particularmente influente. Existem muitas linguagens, incluindo Java, que claramente se inspiraram em Algol, e se o uso de referências nulas foi, em parte, inspirado ou copiado de Algol, Hoare está correto ao assumir parte da culpa pelo custo delas. Eu sinto, no entanto, que sua estimativa é bastante baixa. Um trilhão de dólares pode estar mais próximo do custo real.
CJS
32

Null é uma instância de alguma coisa?

Não. É por isso null instanceof Xque retornará falsepara todas as classes X. (Não se deixe enganar pelo fato de poder atribuir nulla uma variável cujo tipo é um tipo de objeto. Estritamente falando, a atribuição envolve uma conversão implícita de tipo; veja abaixo.)

A que conjunto pertence 'null'?

É o primeiro e único membro do tipo nulo, em que o tipo nulo é definido da seguinte maneira:

"Também existe um tipo nulo especial, o tipo da expressão nulo, que não tem nome. Como o tipo nulo não tem nome, é impossível declarar uma variável do tipo nulo ou converter para o tipo nulo. reference é o único valor possível de uma expressão do tipo nulo.A referência nula sempre pode ser convertida para qualquer tipo de referência.Na prática, o programador pode ignorar o tipo nulo e apenas fingir que nulo é apenas um literal especial que pode ser de qualquer tipo tipo de referência." JLS 4.1

O que é nulo?

Veja acima. Em alguns contextos, nullé usado para denotar "nenhum objeto" ou "desconhecido" ou "indisponível", mas esses significados são específicos de aplicativos.

Como isso é representado na memória?

Isso é específico da implementação e você não poderá ver a representação nullem um programa Java puro. (Mas nullé representado como um endereço / ponteiro zero da máquina na maioria, se não em todas as implementações de Java.)

Stephen C
fonte
14

O que é nulo?

Não é nada.

Null é uma instância de alguma coisa?

Não, pois não é nada. Não pode ser instância de nada.

A que conjunto pertence o nulo?

Nenhum conjunto

Como isso é representado na memória?

Se algumas referências apontarem para ele, como:

Object o=new Object();

Na memória de heap, algum espaço atribuído ao novo objeto criado. E o apontará para o espaço atribuído na memória.

Agora o=null;

Isso significa que agora o não apontará para esse espaço de memória do objeto.

Sanjay Jain
fonte
1
"Now o = null; Isso significa que agora o não apontará para o espaço de memória do objeto." Eu acho que esta é a forma como coleta de lixo funciona em JAVA
Hardik Mishra
9

Não, não é a instância de nada, instanceof sempre será falsa.

Tom
fonte
7

A palavra-chave nula é um literal que representa uma referência nula, que não se refere a nenhum objeto . null é o valor padrão das variáveis ​​do tipo de referência.

Talvez também dê uma olhada

null: Glossário Java

Adriaan Stander
fonte
2
Não é uma palavra-chave, é um literal . Má qualidade e citação não normativa.
Marquês de Lorne #
6

Nulo não é uma instância de nenhuma classe.

No entanto, você pode atribuir nulo a variáveis ​​de qualquer tipo (objeto ou matriz):

 // this is false   
 boolean nope = (null instanceof String);

 // but you can still use it as a String
 String x = null;
 "abc".startsWith(null);
Thilo
fonte
6

Nulo em Java (tm)

Em C e C ++, "NULL" é uma constante definida em um arquivo de cabeçalho, com um valor como:

    0

ou:

    0L

ou:

    ((void*)0)

dependendo das opções do compilador e do modelo de memória. NULL não é, estritamente falando, parte do próprio C / C ++.

No Java (tm), "null" não é uma palavra-chave, mas um literal especial do tipo nulo. Pode ser convertido para qualquer tipo de referência, mas não para qualquer tipo primitivo, como int ou booleano. O literal nulo não necessariamente tem valor zero. E é impossível converter para o tipo nulo ou declarar uma variável desse tipo.

p27
fonte
5

Representação de bytecode

O Java nullpossui suporte direto à JVM: três instruções são usadas para implementá-lo:

  • aconst_null: por exemplo, para definir uma variável nullcomo emObject o = null;
  • ifnulle ifnonnull: por exemplo, para comparar um objeto nullcomo emif (o == null)

O capítulo 6 "O conjunto de instruções da Java Virtual Machine" menciona os efeitos de nulloutras instruções: lança um NullPointerExceptionpara muitos deles.

2.4 "Tipos e valores de referência" também menciona nullem termos genéricos:

Um valor de referência também pode ser a referência nula especial, uma referência a nenhum objeto, que será indicado aqui por nulo. A referência nula inicialmente não tem tipo de tempo de execução, mas pode ser convertida para qualquer tipo. O valor padrão de um tipo de referência é nulo.

Ciro Santilli adicionou uma nova foto
fonte
4

nullé um valor especial, não é instância de nada. Por uma razão óbvia, não pode ser instanceofnada.

fastcodejava
fonte
3

nullé um valor especial que não é uma instância de nenhuma classe. Isso é ilustrado pelo seguinte programa:

public class X {
   void f(Object o)
   { 
      System.out.println(o instanceof String);   // Output is "false"
   }
   public static void main(String[] args) {
      new X().f(null);
   }
}
Itay Maman
fonte
6
A única coisa que o exemplo mostra é que nullnão é uma instância de String.
Sasha Chedygov
4
Se você alterou a assinatura para void f(String o), faria mais sentido.
Thile
2

null em Java é semelhante / semelhante a nullptr em C ++.

Programa em C ++:

class Point
{
    private:
       int x;
       int y;
    public:
       Point(int ix, int iy)
       {
           x = ix;
           y = iy;
       }
       void print() { std::cout << '(' << x << ',' << y << ')'; }
};
int main()
{
    Point* p = new Point(3,5);
    if (p != nullptr)
    {
       p->print();
       p = nullptr;
    }
    else
    {
        std::cout << "p is null" << std::endl;
    }
    return 0;
}

Mesmo programa em Java:

public class Point {
    private int x;
    private int y;
    public Point(int ix, int iy) {
        x = ix;
        y = iy;
    }
    public void print() { System.out.print("(" + x + "," + y + ")"); }
}
class Program
{
    public static void main(String[] args) {
        Point p = new Point(3,5);
        if (p != null)
        {
            p.print();
            p = null;
        }
        else
        {
            System.out.println("p is null");
        }
    }
}

Agora você entende pelos códigos acima o que é nulo em Java? Se não, recomendo que você aprenda ponteiros em C / C ++ e então entenderá.

Observe que em C, ao contrário de C ++, nullptr é indefinido, mas NULL é usado em vez disso, o que também pode ser usado em C ++, mas em C ++ o nullptr é mais preferível do que apenas NULL, porque o NULL em C está sempre relacionado a ponteiros e isso é então, em C ++, o sufixo "ptr" foi acrescentado ao final da palavra e agora todas as letras são minúsculas, mas isso é menos importante.

Em Java, cada variável da classe de tipo não primitiva sempre é referência a objeto desse tipo ou herdada e null é referência de objeto de classe nula, mas não ponteiro nulo, porque em Java não existe tal coisa "ponteiro", mas referências a classe objetos são usados ​​e nulo em Java está relacionado às referências a objetos de classe; portanto, você também pode chamá-lo como "nullref" ou "nullrefobj", mas como é longo, basta chamá-lo de "nulo".

Em C ++, você pode usar ponteiros e o valor nullptr para membros / variáveis opcionais , ou seja, membro / variável que não tem valor e, se não tiver valor, será igual a nullptr; portanto, como nulo em Java pode ser usado, por exemplo.


fonte
1

Existem duas categorias principais de tipos em Java: primitivo e referência . Variáveis ​​declaradas de um tipo primitivo armazenam valores; variáveis ​​declaradas de um tipo de referência armazenam referências.

String x = null;

Nesse caso, a instrução de inicialização declara as variáveis ​​"x". "X" armazena a referência de sequência. Aqui é nulo . Antes de tudo, null não é uma instância de objeto válida, portanto, não há memória alocada para ele. É simplesmente um valor que indica que a referência do objeto não está se referindo atualmente a um objeto.

Anand
fonte
0

Uma maneira interessante de ver nulo em java na minha opinião é vê-lo como algo que NÃO denota falta de informação, mas simplesmente como um valor literal que pode ser atribuído a uma referência de qualquer tipo. Se você pensar sobre isso, se denotou ausência de informações, então a1 == a2 é verdadeiro não faz sentido (no caso de ambos terem sido atribuídos a um valor nulo), pois eles poderiam realmente estar apontando para QUALQUER objeto (simplesmente não sei para quais objetos eles devem estar apontando) ... A propósito, null == null retorna true em java. Se java, por exemplo, seria como SQL: 1999, então null == null retornaria desconhecido (um valor booleano no SQL: 1999 pode assumir três valores: verdadeiro, falso e desconhecido, mas na prática o desconhecido é implementado como nulo em sistemas reais) ... http://en.wikipedia.org/wiki/SQL

Bat0u89
fonte
0

Resposta curta e precisa que responde formalmente a todas as suas perguntas da JLS:

3.10.7 O Literal Nulo

O tipo nulo possui um valor, a referência nula, representada pelo literal nulo nulo, formado a partir de caracteres ASCII.

Um literal nulo é sempre do tipo nulo.

Apenas uma referência do tipo que é atribuída a null é alocada. Você não atribui nenhum valor (objeto) à referência. Essa alocação é específica para a JVM quanta referência será necessária e em qual área de memória será alocada.

Oleksii Kyslytsyn
fonte