Continuando.
Ponto 2 - O importante é entender que código é subjetivo. Existem códigos mais rápidos e mais lentos. Códigos melhores de serem mantidos (é mais fácil de alterá-lo) e código mais difícil de serem alterados.
As vezes a regex não é a melhor solução pelo simples fato de ela ficar muito complexa. Imagina você trabalhando com mais 3 programadores e ai você me coloca uma regexp gigântica (por exemplo a de validação de e-mail, pesquise no google). Um belo de um dia, você está de férias e esses 3 programadores precisam mexer justamente naquele código que você fez. Você precisa detestá-los para fazer isso com eles hahahaha.
Ponto 3 - Toda vez que você ver um NullPointerException, a culpa vai ser SUA. Sempre sua. Sempre.
Vamos então entender o NullPointerException:
Quando temos uma variável como a seguinte:
String nome = "Rafael Guerreiro";
A variável NÃO está guardando um valor e NEM um objeto. Então o que ela está guardando? Uma referência.
A referência é, na verdade, AONDE o seu objeto está localizado na sua memória RAM. Então se fizermos o seguinte:
String nome = "Rafael Guerreiro";
String outroNome = nome;
Quantas variáveis temos? 2.
Quantas referências temos? 1.
Quantos objetos temos? 1.
Basicamente, existem 2 variáveis apontando para o mesmo endereço de memória. Endereço de memória é aonde está o seu objeto na sua memória RAM.
Agora, como que faço para ter uma variável que não aponta para endereço nenhum? Basta atribuir null à ela.
String nome = "Rafael Guerreiro";
String outroNome = null;
Quantas variáveis temos? 2.
Quantas referências temos? 1.
Quantos objetos temos? 1.
A diferença aqui é que uma dessas variáveis não aponta para referência alguma.
Então vamos entender os comportamentos de um objeto (métodos). Comportamento é o que o Objeto faz, logo, são os métodos.
Olhando a classe String, ela define que toda String sabe retornar o próprio tamanho, usando o método length().
String nome = "Rafael Guerreiro";
String outroNome = nome;
System.out.println(nome.length()); // 16
System.out.println(outroNome.length()); // Também é 16 pois o Objeto é o mesmo.
O que está acontecendo quando chamamos (invocamos) um método? O ponto (.) define o acesso ao Objeto referenciado pela variável. Basicamente, o programa vai até a memória RAM e procura o objeto para então pedir que ele execute o método solicitado, no caso, o length().
Agora, se uma das váriáveis está null, ou seja, não tem referência para um objeto, como que o nosso programa vai saber qual objeto deve executar aquele método? Ele não tem como saber. Simplesmente por quê não existe nenhum objeto para isso.
Daí ele dispara (throw) um NullPointerException. É uma exceção, algo de inesperado ocorreu no seu programa.
No exemplo que você me mandou:
Exception in thread "main" java.lang.NullPointerException
at Carga.Pendentes.main(Pendentes.java:23)
Ele está te dizendo: “Na linha 23 da Classe Pendentes, você pediu que eu executasse um objeto, mas essa variável não referencia nenhum objeto.”
Como você resolve isso? Assim:
String aaa = null;
if (aaa != null) // Caso essa variável NÃO seja null, caso ela TENHA uma referência a um objeto.
System.out.println(aaa.length());
else // Caso essa variável SEJA null
System.out.println("aaa é null, não consigo saber o tamanho pois eu não tenho o objeto.");
DICA DE OURO
As exceptions, apesar de grandes e assustadoras, estão aqui para nos ajudar. Toda vez que você se deparar com uma, respire fundo e LEIA-A, ENTENDA-A e então corrija seu programa. É para isso que elas servem, para te contar o que deu de errado. Elas só são um pouco feias, mas não tem problema, tente ler mesmo assim. Esforce-se para descobrir por quê aquele erro ocorreu.
http://blog.caelum.com.br/lidando-com-exceptions/ Post no blog da Caelum sobre exceptions. É muito bom e importante.
Sobre o ponto 4, mais para frente tentamos resolvê-lo. Vamos cuidar do 1 e do 3 primeiro.