PROBLEMA errore Exception in thread "main" java.lang.NullPointerException.... come risolvo?

Phoenix530

Utente Attivo
304
21
salve a tutti

dopo la bellezza di 20 anni mi sto rimettendo a ripassare java in quanto ho la possibilitá di accedere ad un corso gratuito avanzato a scopo assunzione. dal momento che mi hanno chiesto una buona infarinatura base, oggi ho deciso di provare a costruire una piccola rubrica telefonica che acquisisce tramite un oggetto contatto, nome, cognome, numero e indirizzo di 5 persone massimo. queste 5 persone sono rappresentate da un array dell'oggetto persone di classe contatto. il codice é strutturato con un menu di selezione iniziale che in base al numero inserito, dovrebbe far inserire i dati, sovrascriverli in caso di array pieno o stampare tutto a video (almeno per il momento, successivamente vorrei portare tutto su un file per il salvataggio).

il problema attuale del codice che mi sta facendo uscire pazzo, é che dopo aver inserito i dati del primo utente, il software mi restituisce:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Contatto.compilazione(String, String, String, String)" because "persone[a]" is null
at Main.main(Main.java:37)

altra cosa strana é che se non inserisco due volte il comando per l'acquisizione del primo valore, lo script passa direttamente al secondo. vi allego il codice. se qualcuno riuscisse a farmi capire dove sta il problema ve ne sarei grato.

Java:
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int selezione=0;
        String nome="a";
        String cognome="a";
        String numero="a";
        String indirizzo="a";
        int a=0, b=0;
        Contatto[] persone = new Contatto[5];

        do{
            //stampa menu e acquisizione opzione:
            System.out.printf("Rubrica 1.0 \n \n Seleziona l'opzione: \n 1- inserisci contatto \n 2- cerca contatto \n 3- salva contatti \n 4- visualizza rubrica completa \n 5- esci \n\n");
            System.out.printf("inserisci numero opzione:");
            //acquisizione opzione.
            selezione=scan.nextInt();
            System.out.println("hai selezionato:"+selezione);

            switch(selezione) {
                case 1:
                    if(a<5) {
                        System.out.println("nome:");
                        //non capisco perche'lo skippa.
                        nome = scan.nextLine();
                        nome = scan.nextLine();
                        System.out.println("cognome:");
                        cognome = scan.nextLine();
                        System.out.println("numero:");
                        numero = scan.nextLine();
                        System.out.println("indirizzo:");
                        indirizzo = scan.nextLine();
                        //passo dati allóggetto:
                        persone[a].compilazione( nome, cognome, numero, indirizzo);
                        a++;
                    }else {
                        System.out.println("memoria piena. seleziona la casella da sovrascrivere(1-5):");
                        b=a;
                        a = scan.nextInt();
                        //inserimento
                        System.out.println("nome:");
                        //non capisco perche'lo skippa se ne metto 1.
                        nome = scan.nextLine();
                        nome = scan.nextLine();
                        System.out.println("cognome:");
                        cognome = scan.nextLine();
                        System.out.println("numero:");
                        numero = scan.nextLine();
                        System.out.println("indirizzo:");
                        indirizzo = scan.nextLine();
                        //passo dati al costruttore dell'oggetto creato
                        persone[0].compilazione(nome, cognome, numero, indirizzo);
                        a=b;
                    }
                    break;
                case 2:
                    //contatto.ricerca();
                    break;
                case 3:
                    // contatto.salva();
                    break;
                case 4:
                    for(int i=0;i<5;i++) {
                        if(persone[i]!=null)
                            persone[i].visualizzaDati();
                        else
                            System.out.println("contatto vuoto");
                    }
                    break;
                case 5:
                    break;
                default:
                    selezione = 0;
            }

            if(selezione==5)
                System.out.printf("grazie per aver usato la rubrica!");
        }while(selezione!=5);

    }
}

Contatto.java
Java:
public class Contatto {
    private String nome;
    private String cognome;
    private String numero;
    private String indirizzo;

    public Contatto() {
        this.nome = "vuoto";
        this.cognome = "vuoto";
        this.numero = "vuoto";
        this.indirizzo = "vuoto";
    }

    public void compilazione(String nome, String cognome, String numero, String indirizzo) {
        this.nome = nome;
        this.cognome = cognome;
        this.numero = numero;
        this.indirizzo = indirizzo;
    }

    public void visualizzaDati() {
        System.out.printf("nome inserito:" + this.nome);
        System.out.printf("cognome inserito:" + this.cognome);
        System.out.printf("numero inserito:" + this.numero);
        System.out.printf("indirizzo inserito:" + this.indirizzo);
    }


}
 
Ultima modifica da un moderatore:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,233
1,865
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
L'eccezione è dovuto al fatto che crei un array di Contatti di 5 elementi, ma tutti gli elementi sono a NULL. Devi creare un'istanza effettiva di quella classe (ovvero creare un oggetto) per poter richiamare su di esso il metodo.

Ah, invece del visualizzaDati() in Java esiste il metodo toStraing, definito se non erro da Object.

L'errore lo puoi risolvere ad esempio facendo così:
Java:
persone[a] = new Contatto();

aggiungilo prima della chiamata al metodo compilazione().

Ps. consiglio spassionato: non mettere tutto nel main, non è una buona pratica. Usa i metodi/funzioni e le classi (il do while potrebbe per esempio rimanere nel main, ma andrebbero richiamate delle funzioni, ciascuna incaricata di un compito). Dipende anche come e quanto vuoi astrarre il tutto; io per esempio farei una classe Rubrica con un array di 5 Contatto al suo interno.
 

BAT

Moderatore
Staff Forum
Utente Èlite
23,074
11,653
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Contatto.java
insomma, non va molto bene
una cosa del genere invece (andrebbero aggiuti i metodi gest/set dei campi, è semplificato)
Java:
class Contatto {
    private String nome;
    private String cognome;
    private String numero;
    private String indirizzo;

    public Contatto() { // fittizio
        super();
    }

    public Contatto(String cognome, String nome, String indirizzo, String numero) {
        this.nome = nome;
        this.cognome = cognome;
        this.indirizzo = indirizzo;
        this.numero = numero;
    }

    @Override
    public String toString() {
        return "Cognome: " + cognome + "   Nome: " + nome + "   Indirizzo: " + indirizzo + "  N. " + numero;
    }
} // FINE classe Contatto

Per i metodi di stampa menu applicazione, lettura di un contatto, stampa della rubrica ti conviene usare delle funzioni statiche da definire nella classe del main, una cosa del genere:
Java:
static void stampaMenu(){
        System.out.println("Scegli l'opzione");
        System.out.println("[1] Inserisci contatto");
        System.out.println("[2] Visualizza contatti");
        System.out.println("[E] Esci\n");
    }
Java:
static Contatto leggiContatto(){
        System.out.println("\n--------------------------");
        System.out.println("Inserimento nuovo contatto");
        System.out.println("--------------------------");
        Scanner sc = new Scanner(System.in);
        System.out.print("Cognome --> ");
        String c = sc.nextLine();
        System.out.print("Nome --> ");
        String n = sc.nextLine();
        System.out.print("Indirizzo --> ");
        String i = sc.nextLine();
        System.out.print("Numero civico --> ");
        String nc = sc.nextLine();
        System.out.println("--------------------------\n");
        return new Contatto(c, n, i, nc);
    }

se fai così il main sarà molto più leggibile
 
  • Mi piace
Reazioni: Phoenix530

Phoenix530

Utente Attivo
304
21
insomma, non va molto bene
una cosa del genere invece (andrebbero aggiuti i metodi gest/set dei campi, è semplificato
Java:
class Contatto {
    private String nome;
    private String cognome;
    private String numero;
    private String indirizzo;

    public Contatto() { // fittizio
        super();
    }

    public Contatto(String cognome, String nome, String indirizzo, String numero) {
        this.nome = nome;
        this.cognome = cognome;
        this.indirizzo = indirizzo;
        this.numero = numero;
    }

    @Override
    public String toString() {
        return "Cognome: " + cognome + "   Nome: " + nome + "   Indirizzo: " + indirizzo + "  N. " + numero;
    }
} // FINE classe Contatto

Per i metodi di stampa menu applicazione, lettura di un contatto, stampa della rubrica ti conviene usare delle funzioni statiche da definire nella classe del main, una cosa del genere:
Java:
static void stampaMenu(){
        System.out.println("Scegli l'opzione");
        System.out.println("[1] Inserisci contatto");
        System.out.println("[2] Visualizza contatti");
        System.out.println("[E] Esci\n");
    }
Java:
static Contatto leggiContatto(){
        System.out.println("\n--------------------------");
        System.out.println("Inserimento nuovo contatto");
        System.out.println("--------------------------");
        Scanner sc = new Scanner(System.in);
        System.out.print("Cognome --> ");
        String c = sc.nextLine();
        System.out.print("Nome --> ");
        String n = sc.nextLine();
        System.out.print("Indirizzo --> ");
        String i = sc.nextLine();
        System.out.print("Numero civico --> ");
        String nc = sc.nextLine();
        System.out.println("--------------------------\n");
        return new Contatto(c, n, i, nc);
    }

se fai così il main sarà molto più leggibile
grazie per i consigli. alla fine grazie ad un amico, sono riuscito a capire il perche' dell'errore. dovevo inizializzare i campi dell'array prima dell'acquisizione dei parametri. domani mattina do una pulita al codice secondo i tuoi suggerimenti e provo a implementare una ricerca per cognome all'interno dell'array.
 

BAT

Moderatore
Staff Forum
Utente Èlite
23,074
11,653
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
dovevo inizializzare i campi dell'array prima dell'acquisizione dei parametri
non è necessario in realtà, anche se da come hai scritto il codice era quello che ti causava ill riferimento null;
l'essenziale è che ci fosse un array i cui elementi fossero di classe Contatto, l'inizializzazione dei singoli elementi dell'array non è necessaria, infatti possono anche essere null
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!