Null pointer exception incompreensível

Boa tarde pessoal

Exercitando a orientação a objetos via apostila caelum, escrevi o seguinte código

public class Conta {
	private static int seq = 0;
	private int num;
	private Cliente titular;
	private double saldo;
	private double limite;
	
	//Construtor que recebe os atributos como parâmetros.
	public Conta(Cliente titular, double saldo, double limite){
		num = ++seq;
		this.titular = titular;
		this.saldo = saldo;
		this.limite = limite;
	}
	
	public int getNum(){
		return this.num;
	}

public class CadContas {
	
	public static Conta[] listaContas = new Conta[10];
	
	public static Conta pesqConta(int num){
		for(Conta obj : listaContas){
			if(obj.getNum() == num){
				return obj;
			}
		}
		return null;
	}

}

import java.util.Scanner;

public class Usuario {
	public static Scanner leia = new Scanner(System.in);

	public static void main(String[] args) {
		pesqClienteConta();
	}
	

	private static void pesqClienteConta() {
		int num;
		System.out.println("===========PESQUISA DE CLIENTE POR NÚMERO DA CONTA===========");
		System.out.print("Entre com o número: ");
		num = leia.nextInt();
		Conta objConta = CadContas.pesqConta(num);
		if (objConta == null) {
			System.out.println("Número de conta inexistente no sistema.");
		} else {
			objConta.mostra();
		}

	}

	
}

Tudo está fucionando corretamente, contudo quando digito um código inexistente, mesmo tendo criado a condição if (objConta == null) {System.out.println(“Número de conta inexistente no sistema.”);}, recebo um null pointer exception, alguém saberia explicar por que?

Obrigado

Poste a stacktrace inteiramente, assim poderemos achar com facilidade a linha do erro. O nullpointer deve estar ocorrendo em outro lugar.

Segue o código completo com o erro.

===========PESQUISA DE CLIENTE POR NÚMERO DA CONTA===========
Entre com o número: 1
Exception in thread “main” java.lang.NullPointerException
at dados.CadContas.pesqConta(CadContas.java:18)
at usuario.Usuario.pesqClienteConta(Usuario.java:138)
at usuario.Usuario.menu(Usuario.java:52)
at usuario.Usuario.main(Usuario.java:13)

package dados;

public class CadContas {

public static Conta[] listaContas = new Conta[10];

public static void cadastrarConta(Conta obj){
	for(int i = 0; i < listaContas.length; i++){
		if(listaContas[i] == null){
			listaContas[i] = obj;
			break;
		}
	}
}

public static Conta pesqConta(int num){
	for(Conta obj : listaContas){
		if(obj.getNum() == num){
			return obj;
		}
	}
	return null;
}

}

package dados;

public class Cliente {
private String nome;
private String cpf;

//Construtor que recebe os atributos como parâmetros
public Cliente (String nome, String cpf){
	this.nome = nome;
	this.cpf = cpf;
}

public String getNome(){
	return this.nome;
}

public String getCpf(){
	return this.cpf;
}

}

/*

  • Private - faz com que ninguém consiga acessar ou modificar os atributos, daí a necessidade de getters e setters
  • Static - variável de classe,
  • */

package dados;

public class Conta {
private static int seq = 0;
private int num;
private Cliente titular;
private double saldo;
private double limite;

//Construtor que recebe os atributos como parâmetros.
public Conta(Cliente titular, double saldo, double limite){
	num = ++seq;
	this.titular = titular;
	this.saldo = saldo;
	this.limite = limite;
}

public int getNum(){
	return this.num;
}

public double getSaldo(){
	return this.saldo;
}
public void setSaldo(double saldo){
	this.saldo = saldo;
}

public double getLimite(){
	return this.limite + this.saldo;
}
public void setLimite(double limite){
	this.limite = limite + this.saldo;
}


public void mostra(){
	System.out.println("Número da conta: " + this.num);
	System.out.println("Cliente: " + this.titular.getNome());
	System.out.println("CPF: " + this.titular.getCpf());
	System.out.println("Saldo: " + this.saldo);
	System.out.println("Limite: " + this.limite + "\n");
}

}

package usuario;

import java.util.Scanner;

import dados.Cliente;
import dados.Conta;
import dados.CadContas;

public class Usuario {
public static Scanner leia = new Scanner(System.in);

public static void main(String[] args) {
	menu();
}

public static void menu() {

	int opcao;
	do {
		System.out.println("============================");
		System.out.println("      SIS VITURAL BANK      ");
		System.out.println("============================");
		System.out.println("[1] CADASTRAR NOVA CONTA");
		System.out.println("[2] SACAR");
		System.out.println("[3] DEPOSITAR");
		System.out.println("[4] VISUALIZAR SALDO");
		System.out.println("[5] PESQUISAR CLIENTE POR CONTA");
		System.out.println("[6] LISTAR CLIENTES");
		System.out.println("[0] SAIR");
		System.out.print("OPÇÃO: ");
		opcao = leia.nextInt();
		System.out.println("");
		leia.nextLine();// limpeza de buffer
		switch (opcao) {
		case 1:
			cadastrarNovaConta();
			break;

		case 2:
			sacar();
			break;

		case 3:
			depositar();
			break;

		case 4:
			verSaldo();
			break;

		case 5:
			pesqClienteConta();
			break;

		case 6:
			listarContas();
			break;

		case 0:
			break;

		default:
			System.out.println("OPÇÃO INVÁLIDA! DIGITE NOVAMENTE.\n");
		}

	} while (opcao != 0);

}

private static void cadastrarNovaConta() {

	String nomeCliente;
	String cpf;
	double depositoInicial;
	double limite;

	System.out.println("===========CADASTRAR NOVA CONTA===========");
	while (true) {
		System.out.print("Nome cliente: ");
		nomeCliente = leia.nextLine();
		System.out.print("CPF cliente: ");
		cpf = leia.nextLine();
		Cliente objCliente = new Cliente(nomeCliente, cpf);
		System.out.print("Depósito inicial: R$");
		depositoInicial = leia.nextDouble();
		System.out.print("Limite da conta: R$");
		limite = leia.nextDouble();
		Conta objConta = new Conta(objCliente, depositoInicial, limite);
		CadContas.cadastrarConta(objConta);
		System.out.println("Cliente cadastrado com sucesso!");
		System.out.print("Deseja cadastrar mais clientes(s/n)?");
		char resp = leia.next().charAt(0);
		System.out.println("");
		if (resp == 'n' || resp == 'N') {
			break;
		}
		leia.nextLine();// limpeza de buffer

	}

}

private static void sacar() {
	int numConta;
	System.out.println("===========SAQUE===========");
	System.out.println("Entre com o número da conta: ");
	numConta = leia.nextInt();
	Conta objConta = CadContas.pesqConta(numConta);
	if (objConta != null) {
		objConta.mostra();
	}
	System.out.println("Confirma saque(s/n)?");
	char confirmacao = leia.next().charAt(0);
	if (confirmacao == 's' || confirmacao == 'S') {
		System.out.print("Entre com o valor a ser sacado: R$");
		double vlrSaque = leia.nextDouble();
		objConta.setSaldo(objConta.getSaldo() - vlrSaque);
		System.out.println("Saque realizado com sucesso!\nSaldo atualizado: R$ "
				+ objConta.getSaldo());
	}
}

private static void depositar() {
	// TODO Auto-generated method stub

}

private static void verSaldo() {
	// TODO Auto-generated method stub

}

private static void pesqClienteConta() {
	int num;
	System.out.println("===========PESQUISA DE CLIENTE POR NÚMERO DA CONTA===========");
	System.out.print("Entre com o número: ");
	num = leia.nextInt();
	Conta objConta = CadContas.pesqConta(num);
	if (objConta == null) {
		System.out.println("Número de conta inexistente no sistema.");
	} else {
		objConta.mostra();
	}

}

private static void listarContas() {
	System.out.println("===========LISTA DE CONTAS===========");

	if (CadContas.listaContas[0] == null) {
		System.out.println("Não há contas cadastradas\n");
	} else {
		for (Conta objConta : CadContas.listaContas) {
			if (objConta != null) {
				objConta.mostra();
			}
		}
	}

}

}

Bom, já é o segundo tópico que vejo você postar dúvida sobre NullPointerExcpetion e usando arrays certo?

Uma coisa que reparei, essa linha:

public static Conta[] listaContas = new Conta[10];

Em nenhum momento do código eu vi você “popular” essa lista, colocando objetos do tipo Conta nela. Se você acha que essa linha já cria uma lista com 10 Contas dentro, está completamente equivocado, porque ela não cria 10 Contas, mas sim 10 espaços para Contas, ou seja, em algum momento você precisa dar new Conta para cada posição da lista, algo como:

for (int i = 0; i < listaContas.length; i++) {
    Conta novaConta = new Conta();
    listaContas[i] = novaConta;
}

Para depois sim, no método pesqConta, você poder usar o if… ou seja, do jeito que está agora, todas as posições do array listaContas estão nulas, faça o seguinte teste no método pesqConta:

public static Conta pesqConta(int num){
    int posicao = 0;
    for (Conta obj : listaContas) {
        if (obj == null) {
            System.out.println("obj nulo na posição: " + posicao + " de listaContas");
        } else if (obj.getNum() == num) {
            System.out.println("obj encontrado na posição: " + posicao + " de listaContas");
            return obj;
        } else {
            System.out.println("obj não encontrado na posição: " + posicao + " de listaContas");
        }
        posicao++;
    }
    return null;
}

Boa noite
Quem irá popular o array será o usuário, veja esse trecho:
`private static void cadastrarNovaConta() {

	String nomeCliente;
	String cpf;
	double depositoInicial;
	double limite;

	System.out.println("===========CADASTRAR NOVA CONTA===========");
	while (true) {
		System.out.print("Nome cliente: ");
		nomeCliente = leia.nextLine();
		System.out.print("CPF cliente: ");
		cpf = leia.nextLine();
		Cliente objCliente = new Cliente(nomeCliente, cpf);
		System.out.print("Depósito inicial: R$");
		depositoInicial = leia.nextDouble();
		System.out.print("Limite da conta: R$");
		limite = leia.nextDouble();
		Conta objConta = new Conta(objCliente, depositoInicial, limite);
		CadContas.cadastrarConta(objConta);
		System.out.println("Cliente cadastrado com sucesso!");
		System.out.print("Deseja cadastrar mais clientes(s/n)?");
		char resp = leia.next().charAt(0);
		System.out.println("");
		if (resp == 'n' || resp == 'N') {
			break;
		}
		leia.nextLine();// limpeza de buffer

	}

}` 

E pelo que compreendi, quando instancio um objeto do tipo array em java Conta[] listaContas = new Conta[10]; as posições terão o valor default null, ou isso não está correto?

Valeu a força.

Acontece que o teste de validação (nesse trecho):

   if (objConta == null) {
	System.out.println("Número de conta inexistente no sistema.");
} else {
	objConta.mostra();
}`      

ocorre depois que a exceção ocorreu (nesse trecho)

Conta objConta = CadContas.pesqConta(num);

e, portanto o javac vai apontar o erro sem entrar no tratamento que você criou. Para resolver esse problema, você deve colocar esses trechos dentro de um try-catch ou lançar uma exceção através do throws.

                private static void pesqClienteConta()
    		{
    			int num;
    			System.out.println("===========PESQUISA DE CLIENTE POR NÚMERO DA CONTA===========");
    			System.out.print("Entre com o número: ");
    			num = leia.nextInt();
    			
    			try
    			{
    				
    				Conta objConta = CadContas.pesqConta(num);
    			}
    			
    			catch(NullPointerException npe)
    			{
    				System.out.println("Número de conta inexistente no sistema.");
    			}
    			
    		}

Ou melhor ainda:

`private static void pesqClienteConta() throws NullPointerException
{
int num;
System.out.println("===========PESQUISA DE CLIENTE POR NÚMERO DA CONTA===========");
System.out.print("Entre com o número: ");

		num = leia.nextInt();
		
		Conta objConta = CadContas.pesqConta(num);
		
		if (objConta == null) 
		{
			System.out.println("Número de conta inexistente no sistema.");
		} 
		else 
		{
			objConta.mostra();
		}
	}`

Acredito que o nullpointer aconteça pq vc testa se o objeto Conta está null, e após o teste manda executar o metodo mostra() desse objeto, e dentro dele existe a propriedade titular. Este sim deve estar null, e a exception acontece quando você tenta chamar o getNome() do titular que está null.

Isso me fez lembrar que todos NullPointerException que recebo são por falta de registro do componente no XML ( Scene Builder). Declaro no .java, mas sempre esqueço de setar no Scene Builder… coisa de iniciante mesmo.

Boa noite cara.

Acho que consegui resolver seu problema…

Na classe “CadContas” eu alterei o ultimo método, onde criei um else e inseri o return null dentro dele.

public static Conta pesqConta(int num){
for(Conta obj : listaContas){
if(obj.getNum() == num){
return obj;
}else{
return null;
}
}
return null;
}

Exatamente! Quando você cria um array Conta[] listaContas = new Conta[10]; todas as 10 posições terão o valor “null”. Você obtém o erro por que está tentando chamar o método “getNum()” de uma posição da array que é “null” no seu método “pesqConta(int num)”.Tente uma das duas soluções propostas pelo LostSoldier que seu código irá funcionar.