NullPointerException Fehler ?

Roman90

Grünschnabel
Hallo erstmal !
Dies ist mein erster Post in diesem Forum, nachdem ich mich hier erst einmal zurecht gefunden habe. Habe vor ca. einem Jahr angefangen zu Programmieren (Java) und praktiziere das auch in der Schule im Fach Datenverarbeitung. Kurz & bündig: Frischling.

Kommen wir zu meinem Problem...

Ich wollte ein Array erstellen, das per Zufall mit Trues und Falses gefüllt ist und daraufhin mit einem Thread die Trues und Falses zählen. Beim Compilieren werden keine Fehler angezeigt, jedoch bekomme ich einen NullPointerException Fehler beim Ausführen der Threads. Versuche schon seid Stunden heraus zu finden was da falsch ist. Bitte um Hilfe...

Klasse Feld
Java:
import java.util.Random;
public class Feld {

  public boolean feld[];

  public void erzeugeArray(int laenge){
    boolean feld[] = new boolean[laenge];
    for(int i = 0; i<=feld.length-1; i++){
       Random r = new Random();
       feld[i] = r.nextBoolean();
    }
    this.feld = feld;
  }
  
  public int getFeldLength(){
    return feld.length;
  }
  
  public boolean[] getFeld() {
    return feld;
  }
}

mein Thread
Java:
import java.util.Random;
public class TolleKlasse extends Thread{

  private int zaehlerTrue = 0 , zaehlerFalse = 0;
  private String meinName;

  public TolleKlasse (String meinName){
   super(meinName);
   this.meinName = meinName;
  }
  
  public String getTheName(){
    return this.meinName;
  }
  
  public void run(){
    Feld f = new Feld();
    for(int y = 0; y<=f.getFeldLength()-1;y++){
      if(f.getFeld()[y] == true){
        zaehlerTrue++;
      }else zaehlerFalse++;
    }
    System.out.println(getTheName()+" Trues: "+zaehlerTrue+" Falses: "+zaehlerFalse);
  }
}

UI (User Interface)
Java:
public class UI {

  public static void main(String[] args) {
     TolleKlasse a = new TolleKlasse("a");
     TolleKlasse b = new TolleKlasse("b");
     Feld f1 = new Feld();
     f1.erzeugeArray(3);
     a.start();
     b.start();
  }
}
 
In der run-Methode des Threads legst du zwar eine neue Instanz der Klasse "Feld" an, rufst aber nie "erzeugeArray" auf. Deshalb bekommst du beim Zugriff auf das Array in dieser Zeile

Java:
for(int y = 0; y<=f.getFeldLength()-1;y++){

bzw.

Java:
return feld.length;

die Nullpointer-Exception.
Diese besagt ja nichts weiter als das deine Variable "feld" auf keinen Speicherbereich zeigt.
 
Vielen Dank schon mal für die so erstaunlich schnelle Antwort!
Okay, nun weiß ich was ich falsch gemacht habe aber wie kann ich denn nun auf das Array zugreifen (Thread Zeile 19, 20) ? Jemand eine Idee?
 
Sollen beide Threads auf dem gleichen Array arbeiten?
Falls ja, musst du dir Gedanken um Synchronisation machen. Außerdem sollte dann sinnvollerweise der eine Thread Vorne anfangen und bis zur Mitte laufen und der andere ab der Mitte bis zum Ende, sonst machen ja beide das gleiche. Auf das Array kannst du zugreifen, in dem du der "TolleKlasse" im Kontruktor noch eine Referenz auf das Array aus der main-Methode mit gibst.

Wenn beide Threads unabhängig auf zwei verschiedenen Arrays arbeiten sollen, musst du die run-Methode nur um eine weitere Zeile ergänzen.

Java:
public void run(){
    Feld f = new Feld();
    
    //Diese Zeile ist neu
    f.erzeugeArray();

    for(int y = 0; y<=f.getFeldLength()-1;y++){
      if(f.getFeld()[y] == true){
        zaehlerTrue++;
      }else zaehlerFalse++;
    }
    System.out.println(getTheName()+" Trues: "+zaehlerTrue+" Falses: "+zaehlerFalse);
  }

Und du kannst jetzt aus der main-Methode das Feld komplett streichen.
 
Tut mir leid, ich hätte wohl am Anfang den "gewünschten" Ablauf etwas näher beschreiben sollen. Aufgabe war es die Threads parallel auszuführen. Also beide Threads greifen auf das bereits in der UI erstellte Feld zu und zählen die Trues und Falses.
Natürlich ist es in einer gewissen Hinsicht sinnlos, jedoch wollte unsere Lehrerin zur Einführung der Threads uns erst einmal nichts großartiges schreiben lassen.
 
Na dann musst du nur das Feld im Konstruktor an beide Threads übergeben. Und da beide nur lesend auf das Array zugreifen, brauchst du dir auch über Synchronisation keine Gedanken machen (dazu werdet ihr dann noch kommen). Ich habs mal schnell angepasst:

Feld
Java:
import java.util.Random;
public class Feld {
	
	public boolean feld[];
	
	public void erzeugeArray(int laenge){
		boolean feld[] = new boolean[laenge];
		Random r = new Random();
		
		for(int i = 0; i<=feld.length-1; i++){
			feld[i] = r.nextBoolean();
		}
		this.feld = feld;
	}
	
	public int getFeldLength(){
		return feld.length;
	}
	
	public boolean[] getFeld() {
		return feld;
	}
}

Thread
Java:
import java.util.Random;
public class TolleKlasse extends Thread{
	
	private int zaehlerTrue = 0 , zaehlerFalse = 0;
	private String meinName;
	private Feld feld;
	
	public TolleKlasse (String meinName, Feld feld){
		super(meinName);
		this.meinName = meinName;
		this.feld = feld;
	}
	
	public String getTheName(){
		return this.meinName;
	}
	
	public void run(){
		for(int y = 0; y<=feld.getFeldLength()-1;y++){
			if(feld.getFeld()[y] == true){
				zaehlerTrue++;
			}else zaehlerFalse++;
		}
		System.out.println(getTheName()+" Trues: "+zaehlerTrue+" Falses: "+zaehlerFalse);
	}
}

Main
Java:
public class UI {
	public static void main(String[] args) {
		Feld f1 = new Feld();
		f1.erzeugeArray(3);
		
		TolleKlasse a = new TolleKlasse("a", f1);
		TolleKlasse b = new TolleKlasse("b", f1);
		a.start();
		b.start();
	}
}
 
ich hab noch schnell ne anmerkung zu der sache mit dem NAMEN ...
warum speicherst du den namen in der klasse extra ein zweites mal und stellst dann noch eine zweite methode zum erfragen dessen bereit ?
java.lang.Thread hat bereits die methode String Thread.getName() der den im konstruktor übergebenen namen *super(String)* zurückgibt ...
eigentlich hätte es dir auffallen sollen @ CPloy
 
Ja, ich bin wie gesagt noch ein Neuling was das Programmieren angeht und demnach auch noch nicht so wirklich fit. Das die Klasse Thread schon eine getName Methode hat wusste ich noch nicht. Aber danke trotzdem für deinen Verbesserungs-/Verschönerungsvorschlag !
 
nunja ... kann ma ja nem neuling nich übelnehmen ...
mich wundert es nur weil du bewusst den konstruktor Thread(String s) verwendet hast der den namen dann zuweist ... desshalb meine rückfrage ob das so stimmt weil es für was anderes brauchst um z.b. access-limits zu umgehen ... aber wenns nur unwissenheit war dann wars bei dir lediglich overhead der raus kann ^^
 

Neue Beiträge

Zurück