Exception in thread "Thread-8" java.lang.NullPointerException

di il
7 risposte

Exception in thread "Thread-8" java.lang.NullPointerException

Salve a tutti.
È da un po' di tempo che combatto con questo errore: Exception in thread "Thread-7" java.lang.NullPointerException.

Questa è la mia classe main:
package giococoniglio;

import java.awt.Dimension;
import javax.swing.JFrame;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

/**
 *
 * @author tinti
 */
public class GiocoConiglio extends Canvas implements Runnable, MouseMotionListener, KeyListener, MouseListener{
    private static final int larghezza = 1355;
    private static final int altezza = 725;
    private static final String nome_gioco = "Niglio Noè!";
    
    BufferedImage foresta = null;
    BufferedImage topo = null;
    BufferedImage gatto = null;
    BufferedImage sasso = null;
    BufferedImage carota = null;
    BufferedImage freccia = null;
    
    private boolean giocoAttivo = false;
    
    private Topo ogg_topo;
    private Freccia ogg_freccia;
    private PioggiaSasso pioggias;
    private PioggiaCarote pioggiac;
    
    public static ArrayList <Freccia> frecce;
    
    public GiocoConiglio(){
        caricaRisorse();
        iniziaGioco();
    }
    
    public static void main(String[] args) {
        GiocoConiglio gioco = new GiocoConiglio();
        
        JFrame finestra_gioco = new JFrame(nome_gioco);
        
        Dimension dimensione_finestra = new Dimension(larghezza,altezza);

        finestra_gioco.setPreferredSize(dimensione_finestra);
        finestra_gioco.setMaximumSize(dimensione_finestra);
        finestra_gioco.setResizable(false);
        
        finestra_gioco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        finestra_gioco.add(gioco);
        gioco.addMouseMotionListener(gioco);
        gioco.addMouseListener(gioco);
        
        finestra_gioco.pack();
        finestra_gioco.setVisible(true);
        
        Thread thread_gioco = new Thread(gioco);
        thread_gioco.start();
        
        
    }
    
    private void iniziaGioco(){
        ogg_topo = new Topo(topo, freccia, 300, 90, 152,this);
        pioggias = new PioggiaSasso(sasso, 1, 700, this);
        pioggias.start();
        pioggiac = new PioggiaCarote(carota, 1, 2000, this);
        pioggiac.start();
    }
    
    private void caricaRisorse(){
        CaricatoreImmagini loader = new CaricatoreImmagini();
        foresta = loader.caricaImmagine("/Immagini/foresta.png");
        topo = loader.caricaImmagine("/Immagini/coniglio.png");
        sasso = loader.caricaImmagine("/Immagini/sasso.png");
        carota = loader.caricaImmagine("/Immagini/carota.png");
        freccia = loader.caricaImmagine("/Immagini/freccia.png");
    }
    
    private void disegna(){
        
        BufferStrategy buffer = this.getBufferStrategy();
        if(buffer == null){
            createBufferStrategy(2);
            return;
        }
        BufferStrategy buffer2 = this.getBufferStrategy();
        if(buffer2 == null){
            createBufferStrategy(3);
            return;
            }
        
        BufferStrategy buffer3 = this.getBufferStrategy();
        if(buffer3 == null){
            createBufferStrategy(4);
            return;
            }
        
        BufferStrategy buffer4 = this.getBufferStrategy();
        if(buffer4 == null){
            createBufferStrategy(5);
            return;
            }
        
        BufferStrategy buffer5 = this.getBufferStrategy();
        if(buffer5 == null){
            createBufferStrategy(6);
            return;
            }
        
        Graphics g = buffer.getDrawGraphics();
        
        g.drawImage(foresta,0,0,larghezza,altezza, this);
        
        ogg_topo.disegna(g);
        pioggias.disegna(g);
        pioggiac.disegna(g);
        
        
        g.drawString("VITA NOÈ:"+ogg_topo.vita, 50, 50);
        g.drawString("PUNTEGGIO :"+ogg_topo.punteggio, 50, 30);
        
        if(frecce != null){
            for(Freccia f : frecce){
                f.disegna(g);
            }
        }
        
        g.dispose();
        buffer.show();
        buffer2.show();
        buffer3.show();
        buffer4.show();
        buffer5.show();
    }
    
    private void aggiorna(){
        
        ArrayList<Sasso> sassi = pioggias.getSassi();
        
        for(Sasso sasso : sassi){
            
            if(GestoreCollisioni.ControllaCollisione(ogg_topo, sasso)){
                sassi.remove(sasso);
                ogg_topo.vita -= 10;
                break;
            }
            if(GestoreCollisioni.ControllaCollisione(ogg_freccia,sasso)){
            	sassi.remove(sasso);
            } 
        }
        
        ArrayList<Freccia> frecce;
        
        ArrayList<Carota> carote = pioggiac.getCarote();
        
        for(Carota carota : carote){
            
            if(GestoreCollisioni.ControllaCollisione(ogg_topo, carota)){
                carote.remove(carota);
                ogg_topo.vita += 5;
                ogg_topo.punteggio += 10;
                break;
            }
        }
        
        
        
        if(controllaVittoria()){
            this.giocoAttivo = false;
            
        }
        
        if(controllaSconfitta()){
            this.giocoAttivo = false;
        }
    }
    
    private boolean controllaVittoria(){
        if(ogg_topo.punteggio >= 100){
            return true;
        }
        return false;
    }
    
    private boolean controllaSconfitta(){
        if(ogg_topo.vita <= 0){
            return true;
        }
        return false;
    }
    
    @Override
    public void run() {
        giocoAttivo = true;
        while(giocoAttivo){
            aggiorna();
            disegna();
        }
    }
    
    public int getLarghezza(){
        return larghezza;
    }
    
    public int getAltezza(){
        return altezza;
    }
    
    

    @Override
    public void mouseMoved(MouseEvent e) {
        int posizione = (e.getPoint().x)-(ogg_topo.getLarghezza()/2);
        
        if(posizione >= 0 && (posizione+ogg_topo.getLarghezza()) <= larghezza){
            ogg_topo.setX(posizione);
        }  
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {
        ogg_topo.spara();
    }

    @Override
    public void mouseDragged(MouseEvent e) {}

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {}


    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) { }

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}
}
Questo è l'errore:
Exception in thread "Thread-8" java.lang.NullPointerException
	at giococoniglio.GestoreCollisioni.ControllaCollisione(GestoreCollisioni.java:15)
	at giococoniglio.GiocoConiglio.aggiorna(GiocoConiglio.java:162)
	at giococoniglio.GiocoConiglio.run(GiocoConiglio.java:211)
	at java.lang.Thread.run(Thread.java:748)

La classe incriminata è:
package giococoniglio;


public class GestoreCollisioni {
    
    public static boolean ControllaCollisione(Topo topo, Sasso sasso){
        return topo.getBordi().intersects(sasso.getBordi());
    }
    
    public static boolean ControllaCollisione(Topo topo, Carota carota){
        return topo.getBordi().intersects(carota.getBordi());
    }
    
    public static boolean ControllaCollisione(Freccia freccia, Sasso sasso){
15        return freccia.getBordi().intersects(sasso.getBordi());
    }
}
Alla riga 15.

Con le altre classi la collisione funziona.
Non capisco perché con questa mi dia errore.

Come posso fare?

7 Risposte

  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    Una NPE viene sollevata quando si cerca di accedere ad un metodo di un oggetto che è nullo.
    Nel tuo caso le ipotesi sono solo 4:

    1) freccia è null
    2) freccia.getBordi() restituisce null
    3) sasso è null
    4) sasso.getBordi() restituisce null (ma non dovrebbe essere questo il caso, altrimenti la NPE verrebbe sollevata dall'intersect() e non dal tuo metodo)

    Controlla quale di queste è vera. Per "far presto" puoi mettere delle stampe dei 4 oggetti dentro al metodo, così quando viene richiamato controlli in console cosa viene stampato.

    Così, a naso, direi che è "ogg_freccia" ad essere nullo. Ho scorso tutto il codice della classe GiocoConiglio e non ho visto assegnazioni a tale oggetto.

    Ciao.
  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    Salve.

    Ho riguardato tutto il codice ma non ho ancora capito come fa ogg_freccia ad essere nullo.

    Questa è la classe della Frecca.

    Ma tutto sembra tornare compreso getBordi().


    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    package giococoniglio;
    
    import java.awt.Graphics;
    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    /**
     *
     * @author tinti
     */
    public class Freccia extends Thread {
        private boolean attivo;
        private int x;
        private int y;
        private int altezza;
        private int larghezza;
        private final float velocità = 30;
        private BufferedImage img_freccia;
        private GiocoConiglio main;
        
        public Freccia(BufferedImage image, int x, int y, int altezza, int larghezza, GiocoConiglio main){
            this.x = x;
            this.y = y;
            this.altezza = altezza;
            this.larghezza = larghezza;
            this.img_freccia = image;
            this.main = main;
            attivo = false;
            this.start();
        }
        
        
        @Override
        public void run(){
            attivo = true;
            while(attivo){
                aggiorna();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Freccia.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        private void aggiorna(){
            y -= velocità;
            if(y+(altezza) < 0){
                this.setAttivo(false);
                GiocoConiglio.frecce.remove(this);
            }
        }
        
        public void disegna(Graphics g){
            g.drawImage(img_freccia, x, y, larghezza, altezza, main);
        }
        public void setAttivo(boolean stato){
            attivo = stato;
        }
        public int getX(){
            return x;
        }
        public int getY(){
            return y;
        }
        public int getLarghezza(){
            return larghezza;
        }
        public int getAltezza(){
            return altezza;
        }
        
        public void spara(){
            y -= velocità;
        }
        
        public Rectangle getBordi(){
            return new Rectangle(x,y,altezza,larghezza);
        }
    }
    
  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    L'ho scritto: guarda la classe GiocoConiglio.
    Hai dichiarato l'oggetto
    
    private Freccia ogg_freccia;
    
    ma non lo hai mai inizializzato da nessuna parte (da nessuna parte fai ogg_freccia = new Freccia(...)). Eppure nel metodo aggiorna() della stessa classe, fai questa cosa qua:
    
    if(GestoreCollisioni.ControllaCollisione(ogg_freccia,sasso)){
    
    E' lì il problema... stai passando al metodo ControllaCollisione un oggetto nullo.

    Nel metodo iniziaGioco() tu inizializzi correttamente i seguenti oggetti:
    - ogg_topo
    - pioggias
    - pioggiac

    Ma l'oggetto ogg_freccia non lo inizializzi da nessuna parte... è nullo e rimane nullo.

    Ciao.
  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    Ora ho capito.

    Grazie mille per la pazienza e l'aiuto.

    Adesso potrò finalmente concludere il gioco.
  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    @IB|mom: altra cosa da segnalare è che stai "giocherellando" troppo con i thread. Nel tuo codice non si vede alcun accenno alla "sincronizzazione" tra thread, nemmeno per garantire la "visibilità" delle modifiche sulle variabili usate da più thread. Il tuo codice può funzionare ... o non funzionare. Dipende dalla dea bendata ("fortuna") .....

    Ad esempio, sai cosa può succedere se MENTRE stai iterando con
                for(Freccia f : frecce){
                    f.disegna(g);
                }
    Dall'altra parte nell'altro thread fai:
    GiocoConiglio.frecce.remove(this);
    ??

    E sai che anche questo è a maggior ragione scorretto?
            for(Sasso sasso : sassi){
                
                if(GestoreCollisioni.ControllaCollisione(ogg_topo, sasso)){
                    sassi.remove(sasso);     // <---- NO NON PUOI modificare la collezione mentre ci stai iterando sopra!!!
        ....
    Mi spiace ... (ti) serve MOLTO più studio ...
  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    Si io sono ancora alle prime armi e per costruire questa app ho seguito una guida.
    Ma credo che studiando di più saprò scrivere il codice in modo più pulito.
  • Re: Exception in thread "Thread-8" java.lang.NullPointerException

    andbin ha scritto:


            for(Sasso sasso : sassi){
                
                if(GestoreCollisioni.ControllaCollisione(ogg_topo, sasso)){
                    sassi.remove(sasso);     // <---- NO NON PUOI modificare la collezione mentre ci stai iterando sopra!!!
        ....
    Tecnicamente puoi.
    Se non si utilizzano gli iteratori ma gli indici, si può rimuovere un oggetto dalla collezione senza causare eccezioni (cosa che invece succede con gli iteratori).

    Ad esempio, questo codice è corretto:
    
    int i = 0;     //E' possibile utilizzare anche un ciclo for omettendo l'auto-increment, ma non ha molto senso. In questi casi meglio usare un while.
    while( i < myArray.size() ){
        if( checkItem ( myArray.get(i) ) myArray.remove(i);
        else i++;     // incremento soltanto se l'elemento viene rimosso in quanto ArrayList "scala" automaticamente gli altri elementi verso sinistra
    }
    
    Qui il doc del remove: https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#remove-int-

    Mentre con gli iteratori, ad esempio:
    
    MyClass temp;
    Iterator<MyClass> i = myArray.iterator();
    while( i.hasNext() ){
        temp = i.next();
        if( checkItem( temp ) ) myArray.remove(temp));     //<---- Eccezione
    }
    
    Causa un'eccezione, sollevata per l'appunto dall'iteratore stesso.
Devi accedere o registrarti per scrivere nel forum
7 risposte