null != null ?

Status
Nicht offen für weitere Antworten.

Leroy42

Top Contributor
null != null ?

Ich war mir nicht sicher, ob die Frage nicht ins
Swing-Teilforum gehört; schließlicht geht es um
ein JTable. Nach genauerer Analyse, bin ich mir
jedoch sicher, daß es sich nicht um ein Swing-
sondern um ein allgemeines Java-Problem handelt.

Ich erstelle eine Applikation, die es ermöglicht,
Tabellen einer, beim Provider gehosteten Datenbank,
anzuzeigen und anwendungs-zugeschnitte Änderungen
vorzunehmen.

Hierzu habe ich ein inneres, DefaultTableModel
erweiterndes, TableModel geschrieben, daß seine
Daten aus der umgebenden Klasse bezieht um das
dort gelegen JTable zu füttern. Doch wie ich es
auch anstelle, fliegt mir schon während der
Konstruktorabarbeitung, eine NullpointerException
um die Ohren. 🙁

Ich habe den Code, um ihn hier zu posten und
kompilierbar zu belassen, auf's Allernotwendigste
beschnitten; wundert euch also nicht, wenn er
etwas sinnbefreit anmutet. 😎


Code:
import javax.swing.*;
import javax.swing.table.*;

public class Tiny {
	String[][] daten;

	void crash() {
		new JTable(new EModel());
	}
	class EModel extends DefaultTableModel {
		public int getRowCount() {
			// Hier gibts die Exception
			return daten == null ? 0 : daten.length;
		}
	}
	public static void main(String[] args) {
		new Tiny().crash();
	}
}
Ausgabe
Code:
Exception in thread "main" java.lang.NullPointerException
	at Tiny$EModel.getRowCount(Tiny.java:13)
	at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:198)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:98)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:80)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:60)
	at Tiny$EModel.<init>(Tiny.java:10)
	at Tiny.crash(Tiny.java:8)
	at Tiny.main(Tiny.java:17)
Wie man sieht, ruft DefaultTableModel's Konstruktor
bereits getRowCount() auf; hab' ich ja auch nix dagegen.
Aber bereits bei der Abfrage, ob daten null ist, knallts.

Zuerst dachte ich, daß es irgendein Konstruktor
Timerproblem ist, und der Konstruktur der umgebenden
Klasse daten noch nicht erzeugt hat. Deshalb
habe ich den Aufruf in eine zusätzliche Methode crash
verlegt; aber wie man sieht, hat das damit nichts zu tun.

Ganz merkwürdig ist, daß unter Java 1.5 alles problemlos
läuft; aber ich brauche nun mal 1.4 erzeugten Code und der
crasht immer obwohl doch beidesmal die gleichen
Libraries Verwendung finden?

Habe ich jetzt ein Brett (den Maibaum :shock: ) vorm Kopf
oder was ist hier los?
 
Was meinst du mit "zum Testen"?

Die gepostete Klasse ist doch kompilierbar. Nur nicht zum Testen, da es ja
eine Nullpointer-Exception gibt.

Wenn du meine bisherige Real-Klasse meinst:
Code:
	class EModel extends DefaultTableModel {
		public int getColumnCount() {
			return daten!=null ? daten[0].length : 0;
		}
		public String getColumnName(int col) {
			return daten!= null ? daten[0][col] : "";
		}
		public int getRowCount() {
			return daten!=null ? daten.length-1 : 0;
		}
		public Object getValueAt(int row, int col) {
			return daten!=null ? daten[row+1][col] : "";
		}
		public boolean isCellEditable(int row, int col) {
			return false;
		}
	}
 
Komisch, bei mir passiert nichts, wenn ich deinen Code, so wie von dir gepostet aufrufe.

Wenn ich allerdings die Zeile
Code:
return daten == null ? 0 : daten.length;

wie folgt ändere:
Code:
return daten.equals(null) ? 0 : daten.length;

erhalte ich die folgende Fehlermeldung:

Code:
Exception in thread "main" java.lang.NullPointerException
	at Tiny$EModel.getRowCount(Tiny.java:22)
	at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:198)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:98)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:80)
	at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:60)
	at Tiny$EModel.<init>(Tiny.java:19)
	at Tiny.crash(Tiny.java:17)
	at Tiny.main(Tiny.java:27)

Welche JVM hast du?
 
natürlich haut dir daten.equals(null) um die ohren - daten == null, daher geht kein methodenaufruf...

wie er auch geschrieben hat - mit Java1.5 klappst, nur nicht mit 1.4
 
Mit JRE 1.3.0_05 gibt es bei mir auch keine Probleme. Eine 1.4er JRE müsste ich erst noch konfigurieren.
 
abollm hat gesagt.:
Komisch, bei mir passiert nichts, wenn ich deinen Code, so wie von dir gepostet aufrufe.Welche JVM hast du?
JDK 1.5 Da klappts auch, nur wenn ich 1.4 Code erzeuge nicht.

Compilierst du als 1.4 oder 1.5?

Und wie DBC schreibt, daten.equals(null) geht natürlich nicht.
 
Leroy42 hat gesagt.:
abollm hat gesagt.:
Komisch, bei mir passiert nichts, wenn ich deinen Code, so wie von dir gepostet aufrufe.Welche JVM hast du?
JDK 1.5 Da klappts auch, nur wenn ich 1.4 Code erzeuge nicht.

Compilierst du als 1.4 oder 1.5?

Und wie DBC schreibt, daten.equals(null) geht natürlich nicht.

Ich habe sowohl unter 1.5.0_06 als auch unter 1.3.0_05 kompiliert. 1.4 müsste ich - wie geschriben - erst konfigurieren.
 
Eine 1.4er einbinden, will ich ja gar nicht. Es geht nur darum, daß ich 1.4er Code
erzeugen kann, der z.B. auf meinem Provider läuft, der nur eine 1.4er JVM hat.

Wenn ich dem 1.5er Compiler sage, er soll kurz mal 1.4er Code erzeugen, kann dieser
bisher unter jeder 1.4er JVM problemlos genutzt werden.

Kannst du deinem Compiler nicht mal mitteilen, 1.4er zu erzeugen (und nicht
das JDK 1.4 installieren :noe: ) um zu sehen ob der Fehler bei dir auch auftritt?
 
Geil!

Wenn ich das sage:

C:\Programme\Java\jdk1.5.0_06\bin\javac -source 1.4 -target 1.4 Tiny.java

Geht es auch mit der 1.4er Version ausführen 😉

Nur wird beim 1.4er das getRowCount() 1mal mehr aufgerufen als bei der 1.5!!

Habe nämlich eine Ausgabe gemacht und er schreibt mir 3mal null raus (bei 1.4)
Bei 1.5 schreibt er 2mal null raus!

Super ist auch, machst du statt dem Vergleich (daten == null)

Einfach ein System.out.println(daten) dann stellts den dort auf!

Normalerweise sollte er ja einfach null ausgeben, aber stattdesen bekommst ne NPE auf der System.out.println() Zeile!

Glaub das isn Bug!

Test hat gesagt.:
C:\tmp\java>C:\Programme\Java\jdk1.5.0_06\bin\javac -target 1.4 Tiny.java
javac: target release 1.4 conflicts with default source release 1.5

C:\tmp\java>C:\Programme\Java\jdk1.5.0_06\bin\javac -source 1.4 -target 1.4 Tiny.java

C:\tmp\java>java Tiny
null
null

C:\tmp\java>C:\Programme\j2sdk1.4.1_03\bin\java Tiny
null
null
null

das 2te java Tiny = 1.4er , das erste ist 1.5er! Die Ausgabe null ist im getRowCount()
Ich lass dort einfach daten ausgeben!
 
thE_29 hat gesagt.:
C:\Programme\Java\jdk1.5.0_06\bin\javac -source 1.4 -target 1.4 Tiny.java
Geht es auch mit der 1.4er Version ausführen 😉
Warum bei mir aber nicht 🙁

thE_29 hat gesagt.:
Normalerweise sollte er ja einfach null ausgeben, aber stattdesen bekommst ne NPE auf der System.out.println() Zeile!

:shock: Dann fliegt er bei dir ja auch raus oder wie jetzt?
 
Toll, und bei mir kommt in meiner - zufälligerweise erst gestern installierten JRE 1.4.2_08 - im "bin"-Verzeichnis beim Aufruf von java Tiny

Code:
Exception in thread "main" java.lang.UnsupportedClassVersionError: Tiny (Unsupported major.minor version 50.0)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:539)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:55)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)

*grübel*
 
Ha!

Ich habs!

Habs grad durchdebuggt und zwar ist das obergeil!

Code:
public class Tiny {
   protected String daten[][] = null;

   void crash() {
      new JTable(new EModel());
   }

   private class EModel extends DefaultTableModel {
     private int cnt = 0;
   public EModel()
   {
     super();
     System.out.println("NACH SUPER!");
   }
      public int getRowCount() {
        System.out.println("IM GETROWCOUNT!");
        if(cnt <= 1){
          cnt++;
          return 0;
        }
         // Hier gibts die Exception
                 System.out.println(Tiny.this.daten);
         return Tiny.this.daten == null ? 0 : Tiny.this.daten.length;
      }
   }
   public static void main(String[] args) {
      new Tiny().crash();
   }
}

Den Code debugge ich mit Einzelschritt (step by step)

debugger hat gesagt.:
new JTable(new EModel()); -> springt zu Aufruf super();
super(); -> getRowCount(); //wenn ich auf Tiny.this.daten mit der Maus fahre oder sage Inhalt anzeigen, sagt er das gibt es NICHT!!
getRowCount(); -> getRowCount(); //diese Methode wird scheinbar gleich 2mal aufgerufen -> aber jetzt kommts

Nachdem 2ten Aufruf von getRowCount(), springt der debugger erst in die 1te Zeile vom Konstruktor und danach wird cnt auch mal gesetzt!


Dh, der geht automatisch (also vorm Konstruktor schon?!?!) in die getRowCount Methode rein.

Führt man nämlich das Bsp aus, so kommt diese Ausgabe:

Ausgabe hat gesagt.:
IM GETROWCOUNT!
IM GETROWCOUNT!
NACH SUPER!
IM GETROWCOUNT!

Dh, der geht schon 2mal ins getRowCount rein, bevor die innere Klasse überhaupt existiert!

Dadurch kann der auch nicht auf die Variable daten zugreifen => dadurch entsteht eine NPE (eigentlich müsste NoSuchField kommen oder dgl)

Stelle ich auf JDK 1.5 um, so kommt diese Ausgabe
1.5 Ausgabe hat gesagt.:
IM GETROWCOUNT!
IM GETROWCOUNT!
NACH SUPER!

Das ganze wird aber auch mit 1.5 so ausgeführt, nur hat bei 1.5 die innere Klasse bei daten schon null drinnen stehn und bei 1.4 kennt der debugger das Feld gar nicht!

Also isses ein Bug oder sowas und wurde in der 1.5er Version behoben!

Mach das Feld static dann gehts :bae:



@Leoroy: wenn ich javac.exe (1.5) -source 1.4 -target 1.4 sage und via java.exe (1.4) ausführe gehts!
Compiliere ich mit javac.exe (1.4) gehts bei beiden nicht! (Compiliere ich mit 1.5er Version gehts so und so)


Nachtrag: Dadurch das es wenn der 1.5er das compiliert (aber mit 1.4er Angaben) das trotzdem funktioniert, muss der 1.5er Compiler diese Klasse anders verlinken!

Dh, der 1.4er Compiler muss hier einen Fehler haben!
 
???:L

Das werde ich mir später ansehen.

Aber trotzdem schon mal
[schild=11 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1]Vielen Dank!!![/schild]

Du hast anscheinend richtige Terrierqualitäten : Festbeißen bis der Compiler
sich geschlagen gibt. 😎

thE_29 hat gesagt.:
Mach das Feld static dann gehts :bae:
:shock:
So verzweifelt bin ich nun auch wieder nicht.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben