Classe contenitore java


Ho un problema e non capisco come risolverlo.

Quindi ho 3 classi: la prima è main, la seconda è book e la terza è una mensola che contiene alcuni libri.

Classe libro

public class Book {
private String title;
private int year;
private String edition;

public Book(String title, int year, String edition) {
    this.title= title;
    this.year= year;
    this.edition = edition;
}

public Book(Book l)
{
    this.title = l.title;
    this.year = l.year;
    this.edition = l.edition;
}

Classe principale

public static void main(String[] args) {


    Book one = new Book("Title1", first, 2014, "Edition1");
    Book two = new Book("Title2", second, 2013, "Edition2");
    Book three= new Book("Title3", third, 2015, "Edition3");
    Book four = new Book("Title4", fourth, 2015, "Edition4");

    Book[] v = new Book[3];
    v[0] = one;
    v[1] = two;
    v[2] = three;


    Shelf shelf= new Shelf();

   try{

    shelf.append(four);
   }(catch myException e)
    {
       System.out.println(e.toString());
    }

Classe scaffale

public class Shelf {
private Book[] v;

public Shelf() 
{
    v = new Book[3];
}

public void append (Book x) throws myException
{
   if(x != null && v != null)
   {
    Book[] vAppend = new Book[v.length+1];

    for(int i=0; i<v.length; i++)  
    {
        vAppend[i] = new Book(v[i]);
    }
    vAppend[v.length] = new Book(x);
    v = vAppend;

   }
    throw new myException("Null");
}

Come posso fare il metodo append nella classe shelf? Ovviamente mi dà NullPointerException perché l'array che sto usando è null, ma non so come gestirlo.

Un'altra domanda, come faccio inserire oggetti Libro nella classe Scaffale?

All'inizio nel costruttore ho scritto " questo.v = v " quindi quando ho dichiarato un oggetto shelf ho passato il suo array v nella classe principale, che non è nullo, ha funzionato ma l'esercizio ha detto di non farlo in questo modo.

PS Devo fare questo esercizio con un array normale, voglio dire senza ArrayList, devo ancora impararlo.

Author: PM 77-1, 2015-12-01

3 answers

Il problema è nel costruttore Shelf.

public Shelf()
{
    v = new Book[3];
}

Stai inizializzando l'array per essere di dimensione 3, ma non lo riempi mai di libri nel costruttore. Quindi una volta fatto new Shelf() Ha un array di libri di dimensione 3 con 3 valori null in esso.

Quindi, ottieni un NPE perché il tuo metodo append(Book x) presuppone che non ci siano valori null nel tuo array di libri.

public void append(Book x)
{
    Book[] vAppend = new Book[v.length + 1];

    for (int i = 0; i < v.length; i++)
    {
        // ERROR: v.length is 3 but 
        // v[0], v[1], and v[2] will be null initially!!
        vAppend[i] = new Book(v[i]);
    }
    vAppend[v.length] = new Book(x);
    v = vAppend;
}

Per risolvere il problema: Il modo più semplice è cambiare il costruttore per creare un array di dimensioni 0. Poi il resto di il tuo codice lo gestirà.

public Shelf()
{
    v = new Book[0];
}
 1
Author: Andy Guibert, 2015-12-01 00:44:17

Al momento stai espandendo e copiando ogni volta che viene inserito un nuovo libro. Questo non è davvero necessario. Meglio è avere una capacità iniziale che viene espansa solo quando l'array è riempito.

private static final int INCREMENT = 100;
private int capacity = 0;
private int size = 0;
private Book[] books = {};

public void append(Book book) {
    assert book != null;
    expandIfFull();
    books[size++] = book;
}

private void expandIfFull() {
    assert size <= capacity; 
    if (capacity == size) {
        capacity += INCREMENT;
        Book[] copy = new Book[capacity];
        for (int i = 0; i < size; i++)
            copy[i] = books[i];
        books = copy;
    }
}

Questo ha un vantaggio in termini di prestazioni, ma mi sembra anche di rendere più chiaro il tuo intento dividendo il codice di espansione dal codice di aggiunta. Avere un metodo separato significa che può essere chiamato anche nel metodo insert.

È possibile ridurre il codice di espansione utilizzando Arrays metodi ma presumo che il fatto che non sia possibile utilizzare le raccolte Java implica che è necessario farlo manualmente.

Hai anche chiesto come inserire; Ho aggiunto un metodo di esempio per questo. La cosa fondamentale da ricordare è che è necessario spostare i libri dopo la posizione di inserimento dalla fine prima. Altrimenti finirai per copiare lo stesso libro attraverso il resto dell'array.

public void insert(int index, Book book) {
    assert index < size;
    expandIfFull();
    for (int i = size; i > index; i--)
        books[i] = books[i - 1];
    books[index] = book;
    size++;
}
 2
Author: sprinter, 2015-12-01 01:25:15

Potresti usare qualcosa del genere:

public class Shelf {
    private Book[] v;

    public Shelf()
    {
        v = new Book[0];
    }

    public Shelf append (Book x) throws myException
    {
        if(x != null)
        {
            v = Arrays.copyOf(v, v.length + 1);
            v[v.length] = new Book(x);
            return this;
        }
        throw new myException("Null");
    }
 0
Author: Viacheslav Vedenin, 2015-12-01 00:00:07