NullPointerException

kodela

Bekanntes Mitglied
Hallo,

ich habe ein Problem mit eine Liste. Wenn ich ihr Werte zuweisen will bekomme ich den Fehker "NullPointerException".

Hier die Codeschnipsel, die dabei eine Rolle spielen. Zuerst die beiden Klassen:
Java:
    private class ZPOS {
        int zl;
        int sp;
    }
    private class STR8 {
        ZPOS ezPos;
        ZPOS lzPos;
        int len;
    }
Nun mache ich in der übergeordneten Klasse mit folgenem Code eine Liste mit 50 Objekten der Klasse STR8:
Java:
private final STR8[] strList = new STR8[50];
Damit kann ich aber auf die Liste nicht zugreifen, bzw. ihr Werte zuweisen. Also habe ich im Konstruktor folgendes probiert:
Java:
    for (int i = 0; i < strList.length; i++) {
        strList[i] = new STR8();
    }
Aber auch das hilft mir nicht. Was mache ich falsch?

MfG, kodela
 
In welcher Klasse instanzierst du das Array? Wo genau tritt der Fehler auf? (poste doch den StackTrace und den Code auf den er sich bezieht)
 
Danke Joose,

hier ein auszug des betreffenden Codes:
Java:
public class STR8TSAUSWERTUNG implements GlobaleVariablen {
   private final int[][] awStr8ts = new int[9][9];
   . . .
   . . .
   private final STR8[] strList = new STR8[50];

   public STR8TSAUSWERTUNG(Str8tsApp mFrame, Str8ts strKlasse) {
      strApp = mFrame;
      str = strKlasse;
      for (int i = 0; i < strList.length; i++) {
         strList[i] = new STR8();
      }     
   }
   public int initAuswertung(int[] aktStr) {
      int i = 0;
      int z, s;
      boolean str8t;
      int geaendert = 0;

      // aktStr übernehmen
      for (z = 0; z < 9; z++) {
         for (s = 0; s < 9; s++) {
            awStr8ts[z][s] = aktStr[i];
            i++;
         }
      }
      i = 0;
      // Str8ts auflisten, erst die Zeilen
      for (z = 0; z < 9; z++) {
         str8t = false;
         for (s = 0; s < 9; s++) {
            if ((awStr8ts[z][s] & SZELLE) == SZELLE) {
               if (str8t) {
               str8t = false;
               strList[i].lzPos.zl = z;
               strList[i].lzPos.sp = s - 1;
               i++;
               }
            }
            else if (s == 8) {
               strList[i].lzPos.zl = z;
               strList[i].lzPos.sp = 8;
               i++;
            }
            else {
               if (!str8t) {                    // dieser if-Block wird für erste
                  str8t = true;                 // Zuweisung ausgeführt
                  strList[i].ezPos.zl = z;      // <-- hier tritt der Fehler auf (Zeile 75)
                  strList[i].ezPos.sp = s;      // würde bei allen adnderen
               }                                // ebenfalls auftreten
            }
         }
      }
      // Spalten auswerten
      . . .
      . . .
      geaendert = auswertenStr8t();
      . . .
      . . .
      return geaendert;
   }
   . . .
   . . .
   private class ZPOS {
      int zl;
      int sp;
   }
 
   private class STR8 {
      ZPOS ezPos;
      ZPOS lzPos;
      int len;
   }
}
und hier die Fehlermeldung von NetBeans (auch ein Auszug):
Code:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at str8ts.STR8TSAUSWERTUNG.strAuswertung(STR8TSAUSWERTUNG.java:75)
    at str8ts.Str8ts.loeseBasisStrategien(Str8ts.java:1792)
    at str8ts.Str8tsBoard.myKeyPressed(Str8tsBoard.java:464)
    at str8ts.Str8tsBoard.access$100(Str8tsBoard.java:22)
    at str8ts.Str8tsBoard$2.keyPressed(Str8tsBoard.java:101)
Ob das der Stacktrace ist, bin ich mir nicht sicher. Damit habe ich keine Erfahrungen. Zwar fand ich unter der Menüoption "Fenster -> Debugger" die Option "Stackanalyse". In dem sich damit öffnenden Fenster wurde in etwa das selbe angezeigt, wie im Ausgabefenster.

MfG, kodela
 
Hallo,

Problem gelöst. Die innere Klasse und ihre beiden Objekte müssen als "static" deklariert werden, also so:
Java:
    private static class ZPOS {
        static int zl;
        static int sp;
    }
Damit funktioniert alles.

MfG, kodela
 
Weißt du überhaupt warum static geholfen hat und was es tut? (static ist hier nicht! die Lösung)
Hallo Flown,

Nun, um ehrlich zu sein, ich habe zwar versucht, mich schlau zu machen, was es mit statischen Variablen auf sich hat, weiß, dass sie nur einmal angelegt und über die gesamte Laufzeit erhalten bleiben sollen, aber das ist es dann auch schon gewesen.

Dass innere Klassen und alle von außen zugängliche Variablen als statische deklariert werden müssen, habe ich irgendwo im Internet gelesen und als ich es ausprobierte, funktionierte es.

Zugegeben, es wäre schön, wenn man alles, mit dem man sich beschäftigt, in- und auswendig kennen würde, dann bräuchte man eigentlich in keinem Forum dumme Fragen zu stellen. Aber wer kann so etwas von sich schon sagen.

Mancher fährt ganz gut mit dem Auto, hat aber keine Ahnung, wie jeder Teil des Motors genau funktioniert. Na ja, und man kann auch ein wenig programmieren, ohne die Dokumentation für die verwendete Sprache bis auf das letzte Detail zu kennen.

Wenn Du aber weißt, dass static nicht die Lösung ist, dann wäre es sehr nett von Dir, mir und allen übrigen Usern hier die Lösung zu verraten.

MgG, kodela
 
Kurze Erklärung:
Es gibt Klassen und es gibt Instanzen (welche Konkretisierungen einer Klasse sind). Eine Klasse kann es nur einmal geben und Instanzen davon mehrere (außer natürlich es wird mittels DesignPattern verhindert: siehe Singleton).
Das heißt, wenn ich einen Zustand über alle Instanzen hinweg gleich habe und nur an einer Stelle verändern möchte, dann ist static die richtige Wahl (was sehr sehr selten vorkommt - mir kommen jetzt Konstanten gerade in den Sinn so wie Math.PI). Oder wenn eine Methode unabhängig von einem Zustand einer Methode existieren kann - sprich diese hängt nur von den Eingabeparameter ab - kann man sie static machen (siehe Math.sqrt).
Das heißt static gehört zu einer Klasse und braucht keine Instanz um auf sie zuzugreifen. Das impliziert, dass aber jede Instanz Zugriff auf diesen Klassenzustand besitzen - umgekehrt aber nicht (die Klasse kann nicht auf Instanzzustand zugreifen).

Jetzt sollte man wissen das es Standardvalues gibt, wenn eine Variable deklariert wird. Z.B. (aus deinem Beispiel):
Java:
private class ZPOS {
  int zl;
  int sp;
}
private class STR8 {
  ZPOS ezPos;
  ZPOS lzPos;
  int len;
}
Sieht in Realität so aus (vom Compiler hinzugefügt, um genau zu sein):
Java:
private class ZPOS {
  int zl = 0;
  int sp = 0;
}
private class STR8 {
  ZPOS ezPos = null;
  ZPOS lzPos = null;
  int len = 0;
}
Wenn du jetzt kombinierst und ein STR8 Objekt anlegst - wie in deiner Schleife - dann sind die Werte für ezPos und lzPos gleich null.
Darum wurden auch Konstruktoren erfunden, die ein Objekt in einen validen Zustand versetzen und garantieren, dass ein bestimmter anfänglicher Zustand garantiert wird.

ACHTUNG HIER DIE LÖSUNG:

Java:
private class STR8 {
  ZPOS ezPos = null;
  ZPOS lzPos = null;
  int len = 0;

  public STR8() {
    this.ezPos = new ZPOS();
    this.lzPos = new ZPOS();
    // <code>len</code> kann hier auch noch initialisiert werden
  }
}

Das wars zur Lösung und jetzt noch:
Nun, um ehrlich zu sein, ich habe zwar versucht, mich schlau zu machen, was es mit statischen Variablen auf sich hat, weiß, dass sie nur einmal angelegt und über die gesamte Laufzeit erhalten bleiben sollen, aber das ist es dann auch schon gewesen.
Somit habe ich dein Wissen jetzt erweitert und es geht noch weiter. Deine Aussage ist nicht ganz richtig. Die statischen Werte sind nur solange zur Laufzeit zur Verfügung bis sie vom Garbage Collector eingesammelt werden (Advanced Topic!).
Dass innere Klassen und alle von außen zugängliche Variablen als statische deklariert werden müssen, habe ich irgendwo im Internet gelesen und als ich es ausprobierte, funktionierte es.
Man sollte nicht nur lesen, sondern auch verstehen, was man da macht!
Zugegeben, es wäre schön, wenn man alles, mit dem man sich beschäftigt, in- und auswendig kennen würde, dann bräuchte man eigentlich in keinem Forum dumme Fragen zu stellen. Aber wer kann so etwas von sich schon sagen.
Es gibt keine dummen Fragen, nur dumme Antworten. Ich helfe gerne, wenn man auch bereit ist sich ein wenig selbst schlau zu machen, denn es ist hier kein privates Tutorium.
Mancher fährt ganz gut mit dem Auto, hat aber keine Ahnung, wie jeder Teil des Motors genau funktioniert. Na ja, und man kann auch ein wenig programmieren, ohne die Dokumentation für die verwendete Sprache bis auf das letzte Detail zu kennen.
Diese Metapher ist falsch formuliert. Bei "Ein guter Autofahrer sollte sich nicht Wissen wie der Motor funktioniert" sollte das Äquivalent heißen: "Der Java Programmierer sollte nicht wissen wie die JVM funktioniert um gut programmieren zu können". ABER: Er sollte die Grundlegenden Dinge wie OOP, Dokumentation (wissen wo man nachsieht), Sprachkonstrukte sehr wohl verstehen und anwenden! Gleiche wie mit Autofahrer - Straßenregeln, Grundlagen fürs Auto (wo fülle ich Wasser, Benzin, etc. nach) und wie man Auto fahren sollen gut beherrscht werden.
Wenn Du aber weißt, dass static nicht die Lösung ist, dann wäre es sehr nett von Dir, mir und allen übrigen Usern hier die Lösung zu verraten.
Geteilt und bei weiteren Fragen - wie immer - her damit.

EDIT: Code für die Nachwelt ausgebessert!
 
Zuletzt bearbeitet:
Hallo Flown,

ein großes DANKE für die Mühe, die Du Dir mit meiner Anfrage gemacht hast. Jetzt weiß ich zum static-Modifizierer doch etwas mehr.

Ich habe übrigens auf die Verschachtelung der Klassen verzichtet und die Koordinaten für die erste und letzte Zelle einer Str8t im zweidimensionalen Array einzeln aufgeführt. Das ist sogar einfacher in der Handhabung.

Warum in meinem ursprünglichen Konzept die Deklaration der Positions-Klasse und der beiden Koordinaten als static-Elemente geholfen hat, habe ich allerdings noch immer nicht so recht verstanden, muss ich ja jetzt auch nicht mehr.

Interessehalber wollte ich es einmal mit Deinem Code probieren. NetBeans war damit allerdings nicht einverstanden und monierte für die innere Klasse eine geöffnete geschweifte Klammer, obwohl in Deinem Code den zwei öffnenden geschweiften Klammern auch zwei schließende gegenüberstehen.

MfG, kodela
 
Ich habe übrigens auf die Verschachtelung der Klassen verzichtet und die Koordinaten für die erste und letzte Zelle einer Str8t im zweidimensionalen Array einzeln aufgeführt. Das ist sogar einfacher in der Handhabung.
Aber nicht sehr OOP. Multidimensionale Arrays zeugen meist von zu wenig OOP - außer in gewissen Situationen wie Multidimensionale Matrizen. Wenn es einen Punkt gibt, dann sollte es auch eine Klasse dazu geben!
Warum in meinem ursprünglichen Konzept die Deklaration der Positions-Klasse und der beiden Koordinaten als static-Elemente geholfen hat, habe ich allerdings noch immer nicht so recht verstanden, muss ich ja jetzt auch nicht mehr.
Sagen wir vereinfacht: Die Klasse hält die Variablen und die sind bereit, wenn die Klasse geladen wurde (das heißt, wenn sie benötigt wird). Keine Instanz benötigt, sondern einfacher Aufruf mit Klasse.staticVariable.
Interessehalber wollte ich es einmal mit Deinem Code probieren. NetBeans war damit allerdings nicht einverstanden und monierte für die innere Klasse eine geöffnete geschweifte Klammer, obwohl in Deinem Code den zwei öffnenden geschweiften Klammern auch zwei schließende gegenüberstehen.
Ohne ganzen Code und ohne StackTrace kann ich dir da jetzt nicht weiterhelfen.
 
Ohne ganzen Code und ohne StackTrace kann ich dir da jetzt nicht weiterhelfen.
Mit dem StackTrace kann ich leider nicht dienen, da sich NetBeans ja weigert, Deinen Code zu compilieren. Ich habe aber einen Screenshot.

Ein grobes Gerippe von meinem Code habe ich ja hier schon gezeigt. Daran hat sich nicht viel geändert. Die Klasse STR8 ist auf dem Screenshot in der jetzigen Form noch zu sehen. Dann kommt als letztes Dein Code, den ich testen wollte und an dem ich, um Konflikte zu vermeiden, lediglich die beiden Bezeichner geringfügig verändert habe.

Wenn ich mit dem Mauszeiger auf den roten Marker gehe, sagt mir NetBeans, dass eine geschweifte öffnende Klammer (er zeigt das Bild davon) erwartet würde.

Ich habe an meinen funktionierenden Code also lediglich am Ende Deinen Code hinzugefügt.

verschachachtelte_Klasse.PNG
 
ACHTUNG HIER DIE LÖSUNG:
Java:
private class STR8 {
  ZPOS ezPos = null;
  ZPOS lzPos = null;
  int len = 0;

  public class STR8() {
    this.ezPos = new ZPOS();
    this.lzPos = new ZPOS();
    // <code>len</code> kann hier auch noch initialisiert werden
  }
}
Sollte natürlich heißen:
Java:
private class STR8 {
  ZPOS ezPos = null;
  ZPOS lzPos = null;
  int len = 0;

  public STR8() {
    this.ezPos = new ZPOS();
    this.lzPos = new ZPOS();
    // <code>len</code> kann hier auch noch initialisiert werden
  }
}
Aye das passiert, wenn man ohne IDE/Compiler was hier reinstellt. Mea culpa.
 
Vielen Dank euch beiden. Das hat mir jetzt doch viel gebracht. Es war zwar eine Menge Arbeit, alles umzuschreiben, aber so wie es jetzt ist, gefällt es mir doch wesentlich besser.
MfG, kodela
 

Zurück
Oben