NullPointerException

Boa noite, gostaria de tentar entender melhor essa exceção, como funciona em baixo dos panos?

1 - Quem lança a exceção e como ela é detectada? O que eu acho: A JVM lança a exceção, como ela é detectada eu já não sei

2 - NullPointerException é um erro cuja culpa é do programador?

3-O que causa essa exceção?

4 - Qual melhor jeito de evitar essa exceção?

Muito obrigado pela atenção e desculpa pela quantidade de perguntas

Essa exceção acontece quando o código tenta acessar um membro de uma referência nula.

Object x = null;
x.toString(); // NullPointerException

Não sei o que você quer dizer com “como ela é detectada”, se é como a JVM sabe a hora de lançar essa exceção ou como podemos captura-la.

No primeiro caso, acontece um segmentation fault pois o programa tenta acessar uma área de memória nula. A JVM captura esse erro e lança a NPE na thread que estava executando na hora do segfault.

No segundo caso, só colocar um try {} catch (NullPointerException e) {}. Contudo, isso me leva a próxima pergunta. Sim, NPEs são erros de programação.

Evitar trabalhar com valores null é uma boa prática de programação. Ao invés de fazer isso:

Object encontrar(int id) {
    Object resultado = null;
    // tenta achar resultado
    return resultado; // pode retornar null
}

É melhor fazer isso:

Object encontrar(int id) throws ObjetoNaoEncontradoException {
    Object resultado = null;
    // tenta encontrar
    if (resultado == null)
        throw new ObjetoNaoEncontradoException(...);
    return resultado;
}

Evite ao máximo trabalhar com referências nulas. Isso aqui é um belo dum code smell: if ( foo != null ).

Exceção é um evento não esperado que ocorre em tempo de execução, é uma forma de ajudar a identificar erros do sistema.

No java existe uma hierarquia de exceção, classificação de exceção e tipo de throwable.

De uma lida nisso: http://www.devmedia.com.br/trabalhando-com-excecoes-em-java/27601