-

[PROBLEMA] [Java] Array di oggetti non funzionante

#1
Buonasera. Da qualche giorno ho iniziato a studiare Java, a breve inizia un corso di formazione e vorrei portarmi avanti con lo studio.

Sto provando a creare un piccolo programmino che mi permetta di inserire titolo, autore e prezzo di tot libri.

Di conseguenza ho creato una classe ed il main che incollo qui di seguito:

Java:
public class Libro {
    private String nome ="ciao";
    private String autore ="bhu";
    private int costo =1;
 
   //costruttore
public Libro (String nome, String autore, int costo)
{
    this.setNome(nome);
    this.setAutore(autore);
    this.setCosto(costo);
}

public String getNome() {
    return nome;
}

public void setNome(String nome) {
    this.nome = nome;
}

public String getAutore() {
    return autore;
}

public void setAutore(String autore) {
    this.autore = autore;
}

public double getCosto() {
    return costo;
}

public void setCosto(int costo) {
    this.costo = costo;
}
}
Java:
import java.util.*;
public class libreria {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner acquisizione = new Scanner(System.in);

        // inizio variabili dell'oggetto
        String nome="nome";
        String autore="autore";
        int prezzo=1;     
        Libro[] volumi;
      
        // fine variabili dell'oggetto
      
        System.out.println("quanti libri vuoi inserire?: ");
      
        int numeroLibri=acquisizione.nextInt();
        volumi=new Libro[numeroLibri];
      
        for (int numeroOggetto=0; numeroOggetto<5;numeroOggetto++)
        {
            System.out.println("Titolo libro?");
            nome=acquisizione.nextLine();
          
            System.out.println("autore?");
            autore=acquisizione.nextLine();
          
            System.out.println("prezzo?");
            prezzo=acquisizione.nextInt();
          
            volumi[numeroOggetto]= new Libro(nome, autore, prezzo);
        }
      
        for (int numeroOggetto=0; numeroOggetto<5;numeroOggetto++)
        {
            System.out.println(volumi[numeroOggetto]);
        }
    }
}
Anche se in maniera ancora elementare, so lavorare su degli oggetti elementari e tutta la trafila del passargli i parametri con metodi e costruttori, ma ora che sto cercando di creare un array di oggetti non riesco a raccapezzarmici, non capisco perchè non riesco ad invocare il metodo .setNome() per passare il relativo parametro, di conseguenza l'oggetto stampato restituisce dei valori assolutamente insensati.

Abbiate pazienza, ho aperto libri/web e tutorial su java solo da 7 giorni

Ringrazio in anticipo chiunque possa illuminarmi e mettermi sulla via giusta.
 
Ultima modifica da un moderatore:
455
284
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#2
Ciao!
Prima di tutto un consiglio: evita di dare troppi spazi vuoti (specie nella prima classe).

C'è in realtà qualche errore, ad iniziare dall'inizializzazione delle variabili. Questa deve avvenire nel costruttore.
Il metodo getCosto() restituisce double, ma in realtà costo è definito come intero; in questo caso la variabile viene troncata, e di conseguenza perdi la precisione.

Java:
String nome="nome";
String autore="autore";
int prezzo=1;
Questo non ti serve in realtà. Ti è sufficiente dichiararle ed inizializzarle a null o vuote (le stringhe).

Anche qui c'è un errore:
Java:
        for (int numeroOggetto=0; numeroOggetto<5;numeroOggetto++)
leggi "numeroLibri" elementi ma poi utilizzi come limite il valore 5.

L'errore è causato dal fatto che nextInt() non scarta il carattere di nuova riga; dovresti utilizzare ancora nextLine() per scartare il carattere di nuova riga.

Una soluzione migliore è quella di verificare tramite gli "hasNextXxx()" la presenza di token.
Puoi anche utilizzare next() al posto di nextInt() e parsare il valore, trasformandolo in intero:

Java:
numero = Integer.parseInt(acquisizione.next());
Tuttavia non è sicuro in quanto possono essere lanciate eccezioni.
 
#3
Ciao, grazie per la risposta e per i consigli.

Quindi

Java:
 for (int numeroOggetto=0; numeroOggetto<5;numeroOggetto++)
diventa

Java:
 for (int numeroOggetto=0; numeroOggetto<numeroLibri;numeroOggetto++)
e fin qui è chiarissimo. Ho corretto il tipo della variabile nella classe.

Non mi è chiaro invece quando dici che dovrei inizializzare le variabili nel costruttore, puoi farmi un esempio? Perchè sicuramente mi sfugge qualcosa.
 
455
284
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#4
Mi riferisco a questo:

Java:
public class Libro {


    private String nome ="ciao";
    private String autore ="bhu";
    private int costo =1;
   
    
public Libro (String nome, String autore, int costo)
{
    this.setNome(nome);
    this.setAutore(autore);
    this.setCosto(costo);
    
    
}
Non è propriamente corretta quell'inizializzazione. Vedo che hai solo il costruttore con i 3 parametri, quindi per creare l'oggetto devi passare i valori, come fai correttamente nel main().
In questo caso puoi scrivere quelle variabili in questo modo:

Java:
public class Libro {

    private String nome, autore;
    private int costo;
   
public Libro (String nome, String autore, int costo)
{
    this.setNome(nome);
    this.setAutore(autore);
    this.setCosto(costo);
}
senza assegnare valori.

Oltretutto le variabili membro della classe (variabili d'istanza, non so come le chiami) vengono già automaticamente inizializzate con valori di default: le stringhe essendo oggetti hanno come valore di default null; le variabili di tipo int, hanno il valore 0.
 
#5
Ok, corretto ed approfondirò la questione.

Effettivamente

Java:
numero = Integer.parseInt(acquisizione.next());
genera eccezione. In ogni caso, anche passando il prezzo manualmente (quindi dando il valore alla variabile, senza chiederlo all'utente) il programma continua a comportarsi in maniera anomala.

Esempio:

Mi chiede quanti libri voglio inserire (corretto)
subito dopo dovrebbe chiedermi solamente il nome del libro, ma chiede sia il nome che l'autore.
Inoltre, dopo aver inserito i dati richiesti (anche se in maniera assurda, visto l'errore descritto prima), continua a restiture ciò.
Libro@7d4991ad
Libro@28d93b30
Libro@1b6d3586
Libro@4554617c
Libro@74a14482

Mi sa che non è ancora tempo di mettere le mani agli array di oggetti
 
455
284
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#6
Si, perchè tu stampi l'oggetto quando fai questo:

Java:
System.out.println(volumi[numeroOggetto]);
non stai richiamando un metodo della classe. Quando vai a stampare l'oggetto viene usato un codice interno, che è poi il riferimento dell'oggetto.

Tu dovresti richiamare un metodo della classe; un utilizzo comune è l'utilizzo di toString(). E' definito dalla classe Object, e se ne fai l'override, viene richiamato in automatico in situazioni come quella.

Quindi:

Java:
class Libro {

  // blocco riservato alle variabili

  // costruttore

  // metodi della classe

  public String toString() {
    return this->getNome(); // qui puoi fare l'operazione che preferisci
  }
a questo punto quando stampi a video verrà richiamata e tutto funzionerà come ti aspetti.
 
#7
Chiarissimo!!!

Effettivamente avevo totalmente rimosso che per richiamare il valore passato devo passare per il metodo apposito.

Java:
for (int numeroOggetto=0; numeroOggetto<numeroLibri;numeroOggetto++)
        {
           
            System.out.println(volumi[numeroOggetto].getNome() + 
                               volumi[numeroOggetto].getAutore() +
                               volumi[numeroOggetto].getCosto()
                    );
           
        }
Adesso restituisce i valori di nome e prezzo ma continua a non farmi inserire il valore di Autore.

Eppure non penso di sbagliare qualcosa nell'acquisizione dei 3 valori, o meglio, sicuramente si ma non vedo l'errore.
Continua a chiedermi "Titolo libro" e "Autore" contemporaneamente, facendomi inseire un solo valore. Subito dopo mi chiede quello di prezzo che accetta sereamente.

Secondo il ragionamento di prima, suppongo che cosi sia più corretto il passaggio delle variabili ma continua a farmi saltare l'inserimento di "Autore" o di "Nome", non capisco come mai.



Java:
for (int numeroOggetto=0; numeroOggetto<5;numeroOggetto++)
        {
            
            volumi[numeroOggetto]= new Libro(nome, autore, prezzo);
            
            System.out.println("Titolo libro?");
            volumi[numeroOggetto].setNome(acquisizione.nextLine());
            
            System.out.println("autore?");
            volumi[numeroOggetto].setAutore(acquisizione.nextLine());
            
            System.out.println("prezzo?");
            volumi[numeroOggetto].setCosto(acquisizione.nextInt());
            
            
        
            
        }
 
Ultima modifica:
455
284
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#8
No, in quel modo non è corretto: quando crei l'oggetto passi i parametri, che nel tuo caso sono le variabili vuote (o inizializzate con qualche valore, dipende se le hai modificate); successivamente richiami i metodi set, andando a modificare i valori. Quindi non è esattamente corretto quello che fai.
Dovresti richiamare a quel punto il costruttore senza parametri.

Sicuramente comunque quel nextInt() non pulisce lo stream. La nextLine() ripulisce lo stream rimuovendo il carattere "new line", cosa che non avviene con netxtInt().
 
#9
Grazie al tuo preziosissimo aiuto (e qualche testata tra tastiera/manuale apogeo, che cambierò al più presto) penso di aver risolto.
Scrivo "penso" perchè per andare va, ma la soluzione mi pare maledettamente poco elegante.

Suppongo che pratiche per risolvere più elegantemente il problema le acquisirò solo con la pratica e lo studio.

Lascio il codice e come ho risolto, in caso altri dovessero trovare questo scoglio.

Java:
import java.util.*;
public class libreria {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner acquisizione = new Scanner(System.in);
    
        // inizio variabili dell'oggetto
        String nome="";
        String autore="";
        int prezzo=1;       
        Libro[] volumi;
        
        // fine variabili dell'oggetto
        
    
        System.out.println("quanti libri vuoi inserire?: ");
        
        int numeroLibri=acquisizione.nextInt();
      [COLOR=rgb(61, 142, 185)]  acquisizione.nextLine();[/COLOR]
        volumi=new Libro[numeroLibri];
        
        
        
        
        
        for (int numeroOggetto=0; numeroOggetto<numeroLibri;numeroOggetto++)
        {
            
            volumi[numeroOggetto]= new Libro();
            
        System.out.println("Titolo libro?");
            volumi[numeroOggetto].setNome(acquisizione.nextLine());
            
            
            
          System.out.println("autore?");
            volumi[numeroOggetto].setAutore(acquisizione.nextLine());
            
            
            System.out.println("prezzo?");
            volumi[numeroOggetto].setCosto(acquisizione.nextInt());
            [COLOR=rgb(44, 130, 201)]acquisizione.nextLine();[/COLOR]
            
            
            
        
            
        }
        
        for (int numeroOggetto=0; numeroOggetto<numeroLibri;numeroOggetto++)
        {
            
            System.out.println(volumi[numeroOggetto].getNome()+
                               volumi[numeroOggetto].getAutore()+
                               volumi[numeroOggetto].getCosto()
                    );
            
        }
        
    
    }

}
Come hai ben fatto notare, nextInt non consuma l'input fino all'ultimo, di conseguenza rimane "invio" in sospeso, ho quindi aggiunto un nextLine() dopo nextInt per consumare quel carattere.

Come dicevo prima, funziona. È poco elegante ma ci lavorerò su.

Grazie ancora per la pazienza e la cordialità :)
 
Ultima modifica:
Mi Piace: DispatchCode
455
284
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#10
Usando hasNextXxx() avresti un controllo maggiore sul contenuto del prossimo token.

Esistono pure alternative a Scanner comunque, come BufferedReader:

Java:
BufferedReader br = new BufferedReader(new InoutStreamReader(System.in));
Inoltre più avanti vedrai che tutti quanti possono lanciare eccezioni, quindi dovrai utilizzare i blocchi try/catch per catturarle.
 
455
284
Hardware Utente
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Sistema Operativo
Windows 10 64bit
#12
Ah grazie per la correzione. Ero da smartphone ;)
 

Discussioni Simili


Entra