Boa tarde a todos.
O problema que está ocorrendo no loop é um erro de lógica, senão vejamos.
while(nome != null && !nome.equals("fim")) {
....
....
}
Se a variável nome for igual a "Lucas Dourado Fim", obviamente que o nome será diferente de "null" (nome != null) e também será diferente da cadeia de caracteres "fim" (&& !nome.equals("fim")), logo, se voce digitar o nome "Lucas Dourado Fim, o loop while entrará num loop infinito, isto porque o método equals compara a cadeia de caracteres inteira, se toda ele é igual a cadeia de caracteres fornecida pelo usuário.
Até agora estou tentando entender o por quê de você digitar a palavra "Fim" na entrada do nome, e qual a finalidade disto :?: :?: :?: Se ao menos voce quisesse comparar cada letra do String contido no mome, então deveria utilizar o método charAT(int index) ou o indexOf(String char) >= 0, contido na classe String.
Quanto ao declarar o campo telefone como int, muitas pessoas o fazem com o escopo de colocar como regra de validação, para não introduzir caracteres no lugar dos números, o que é uma regra bastante obsoleta, visto que a maioria dos desenvolvedores utilizam máscaras de entrada, e o Java tem este recurso com a classe MaskFormatter, Além do que muitas desenvolvedores já mascaram o telefone assim "([telefone removido]"
Outra coisa que achei desnecessário foi a criação das constantes:
final String PROMPTNome = "Digite o nome de uma pessoa (\"fim\" para terminar): ";
final String PROMPTEnd = "Digite o endereço da pessoa :";
final String PROMPTNumero = "Digite o Numero do Telefone";
final String PROMPTIC = "#";
Constantes nós só declaramos quando as mesmas serão utilizadas mais de uma vez em diversos lugares (diversas classes), isto quando não lembramos qual o valor que as define, por exemplo: "JFrame.ExitOnClose" que possui o valor inteiro 3 (tres), e quando muitas das vezer queremos que o JFrame seja descarregado da memória no momento do seu fechamento, e não lembramos do número que seta a saída do JFrame, fica mais fácil lembrar do nome da constante que "ExitOnClose". É para isto que servem as constantes "final".
Assim sendo, fazendo uma arrumação no seu código, ficaria mais enxuto desta forma:
public class Cadastrar {
private static ArrayList<Pessoa> cad = null;
public static void main(String[] args) {
int opcao = 0;
cad = new ArrayList<Pessoa>();
while (opcao != 2){
System.out.println("Menu Cadastro");
System.out.println("Digite 1 para iniciar cadastro");
System.out.println("Digite 2 para terminar cadastro");
Scanner sc = new Scanner(System.in);
opcao = sc.nextInt();
if (opcao == 1) cadastrarAgenda();
}
}
public static void cadastrarAgenda(){
System.out.println("Cadastrando pessoas.....");
System.out.println("Digite o nome");
Scanner scan = new Scanner(System.in);
String nome = scan.nextLine();
while (nome.equals("")){
System.out.println("Nome não pode ser nulo");
nome = scan.nextLine();
}
System.out.println("Digite o endereço");
String endereco = scan.nextLine();
while (endereco.equals("")){
System.out.println("Endereço não pode ser nulo");
endereco = scan.nextLine();
}
System.out.println("Digite o telefone");
String telefone = scan.nextLine();
while (telefone.equals("")){
System.out.println("telefone não pode ser nulo");
telefone = scan.nextLine();
}
cad.add(new Pessoa(nome, endereco, telefone));
}
}
Repare que eu declarei o ArrayList de cadastro como atributo stático e privado dentro do escopo da classe, isto porque se voce o passasse como parâmetro no método cadastrarAgenda, voce correria o risco de instanciar vários objetos ArrayList contendo apenas um único cadastro, e assim, como atributo privado na classe, voce só faz referência a um único objeto ArrayList.
Veja também como configurei algumas regras de validações simples dentro do método cadastrarAgenda, de modo que o mesmo ficou bem enxuto.
Quanto ao digitar aquela palavra "Fim" no mome, ainda fiquei com a dúvida, e gostaria que voce postasse aqui qual a finalidade disto.
Um abraço.