Kann ich die Nullpointer Exception umgehen

Nico1999

Aktives Mitglied
Hi die Funktion macht die Ausgangsstellung für ein Damenspiel
Java:
public void ausgangsAufstellung() {
        for (int i=0;i<this.größe;i++) {
            for(int j=0;j<this.größe;j++) {
                if(i<(this.größe-2)/2&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {
                    this.damenbrett.get(i)[j].setFigur(new Bauer(i,j,Farbe.WEIS,"BW"));
                }else if((i==this.größe/2|i==this.größe/2+1)&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {
                    this.damenbrett.get(i)[j].setFigur(null);
                }else if(i>this.größe/2+1&&i<this.größe&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {
                    this.damenbrett.get(i)[j].setFigur(new Bauer(i,j,Farbe.SCHWARZ,"BS"));
                }               
            }
        }
    }
Wenn ich das jetzt ausdrucken möchte und nur BS für schwarz und BW für weiß kann ich das ja nicht über
Java:
System.out.println(this.damenbrett(x)[y].getFigur().getTyp)
// also BS oder BW oder null
machen, da ich da ne nullpointerexception bekomme, also wie gebe ich das am besten in der konsole aus, dass auf meine Feld nichts steht ?
 
Oh, da gibt da viele Möglichkeiten. Persönlich bevorzuge ich den Weg, null zu vermeiden, aber natürlich kann man auch mit null arbeiten, beispielsweise mit einer Hilfsmethode

Java:
String formatTyp(Figur figur) {
    return figur == null ? "--" : figur.getTyp();
}

lässt sich schreiben:
Java:
System.out.println(formatTyp(damenbrett(x)[y].getFigur()));
 
du kannst ja deinem feld einfach ne methode geben
Java:
public boolean IstBesetzt(){
    return this.figur != null;
}
und das rufst du einfach auf bevor du getfigur machst somit ist der zugriff gesichert dass es kein nullpointer ist wenn das feld besetzt ist
 
zzusätzlich wüde ich dir mal auslagern empfehlen da du doppelten code hast

kommt jetzt drauf an, sind i und j des bauern zugreifbar? wenn aj könntest du sowas machen

Java:
public void setOnField(Figur figur)
{
    this.damenbrett(figur.x)[figur.y].setFigur(figur)
   
}
public void InitializeEmpty(int i,int j)
{
    this.damenbrett(figur.x)[figur.y].setFigur(null);
}
somit wird dein code zu
Java:
if(i<(this.größe-2)/2&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {
                   setOnFeld(new Bauer(i,j,Farbe.WEIS,"BW"));
                }else if((i==this.größe/2|i==this.größe/2+1)&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {
                    initializeEmpty(i,j);
                }else if(i>this.größe/2+1&&i<this.größe&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {
                    setOnFeld(new Bauer(i,j,Farbe.SCHWARZ,"BS"));
                }
wäre lesbarer

verglichen mit deinen früheren code posts ist es aber eh schon viel besser geworden

wenn du in deiner IDE auf rechtsklick drückst und alles in einem if makierst in der boolean anweisung kannst du "inline method" das wirft dir irgendso was aus
Java:
public boolean IstWeisserBereich(...){
    return i<(this.größe-2)/2&&(sindXYUngerade(i,j)|sindXYGerade(i,j);
}
somit hast du in der obrigen methode das zb

Java:
if(istWeisserBereich(...)) {

                   setOnFeld(new Bauer(i,j,Farbe.WEIS,"BW"));

                }else if((i==this.größe/2|i==this.größe/2+1)&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {

                    initializeEmpty(i,j);

                }else if(i>this.größe/2+1&&i<this.größe&&(sindXYUngerade(i,j)|sindXYGerade(i,j))) {

                    setOnFeld(new Bauer(i,j,Farbe.SCHWARZ,"BS"));

                }
somit erreichst du dass die komplexe methode komplett unkmomplex wird

jeder hans dampf versteht
"wenn weißer bereich setz weißer bauer auf feld"

obwohl man keinen pfenning ahnung hat was erfüllt sein muss und was exakt genau erfüllt sein muss

wenn du jetzt merkst dass du dich verrechnet hast, zb in einer if bedingung "soll eig da passieren"
dann musst du NUR in "istweisserbereich"schauen .. bzw den anderen ausgelagerten if teilen..und dann wird das "bug fixen" plötzlich gar nicht mehr schwer

ich sehs oft auf twitch wo "proffesionelle entwickler" durch ne 300 zeiler methode durchscrollen und versuchen irgendwo den bug zu finden

wenn man halbwegs clean code gebacken kriegt ( if auslagern indem man rechtsklick drückt...sollte verkraftbar sein... oder inhalt in einem block also set on figur auslagert) ist das ganze gar nicht mehr so schwer

und dann kann man weiter gehen und noch mehr in clean code investieren und schwerere sachen anpacken..und dann werden die plötzlich auch nicht mehr schwer

PS dieses "refactoring in clean code" ... ist das mindeste ... warum? weil du in der IDE nur makieren musst... rechtsklick ...refactoring... und dann halt das entsprechende anklicken
das braucht 0 wissen.. nur man muss wissen dass es das gibt
 
Oh, da gibt da viele Möglichkeiten. Persönlich bevorzuge ich den Weg, null zu vermeiden, aber natürlich kann man auch mit null arbeiten, beispielsweise mit einer Hilfsmethode
wie kann ich den null in diesem Fall vermeiden, wie soll ich sonst sagen das auf dem Feld , das die klassenvariable Figur hat sagen, dass keine figur da ist.
Java:
String formatTyp(Figur figur) {
    return figur == null ? "--" : figur.getTyp();
}
diese Anweisung verstehe ich nicht was bedeutet das ? und dass dahinter
du kannst ja deinem feld einfach ne methode geben
Java:
public boolean IstBesetzt(){
    return this.figur != null;
}
und das rufst du einfach auf bevor du getfigur machst somit ist der zugriff gesichert dass es kein nullpointer ist wenn das feld besetzt ist
so eine ähnliche methode habe ich schon bereits ich möchte aber auch das irgentwas in der konsole ausgeben wird für das das Feld figur null hat .
zzusätzlich wüde ich dir mal auslagern empfehlen da du doppelten code hast

kommt jetzt drauf an, sind i und j des bauern zugreifbar? wenn aj könntest du sowas machen
was meinst du mir zugreifbar ? hier mal die Bauern klasse getter setter usw sind auch dabei
Java:
public class Bauer{
    private Koordinaten position;
    private Farbe farbe;
    private Typ typ;
Bauer(int x, int y, Farbe farbe, String typ){
    this.position = new Koordinaten(x,y);
    this.farbe=farbe;
    this.typ=typ
}
}
wenn man halbwegs clean code gebacken kriegt ( if auslagern indem man rechtsklick drückt...sollte verkraftbar sein... oder inhalt in einem block also set on figur auslagert) ist das ganze gar nicht mehr so schwer

und dann kann man weiter gehen und noch mehr in clean code investieren und schwerere sachen anpacken..und dann werden die plötzlich auch nicht mehr schwer

PS dieses "refactoring in clean code" ... ist das mindeste ... warum? weil du in der IDE nur makieren musst... rechtsklick ...refactoring... und dann halt das entsprechende anklicken
das braucht 0 wissen.. nur man muss wissen dass es das gibt
das die IDE das kann wusste ich danke für die Info
 
diese Anweisung verstehe ich nicht was bedeutet das ? und dass dahinter
Das ist der Ternäre Operator: https://de.myservername.com/ternary-operator-java-tutorial-with-examples

Das ist einfach nur eine Kurzform für:
Java:
String formatTyp(Figur figur) {
    if (figur == null) return "--";
    else return figur.getTyp();
}

Aber ich würde generell die anderen Ideen aufgreifen und das Konzept so umändern, dass da ein null nicht vorkommen kann (Wie schon in #2 von @mihe7 erwähnt)

Wenn man das Damebrett sieht, dann hat jedes Feld eine Figur und die kann ein Element einer Enum sein:
NONE, PAWN_BLACK, PAWN_WHITE, QUEEN_BLACK, QUEEN_WHITE.

==> Du brauchst nicht mehrere Instanzen einer Figur, so es Dir nur um die entsprechende Feldbelegung geht. Die Figut hat dann auch keine Koordinate und so. Das wäre ja auch doppelt gespeichert, den du hast ja schon die Zuweisung zu einem bestimmten Feld.

Und die Darstellung kann dann auch relativ einfach in einer Ausgabe Klasse sein, z.B. mittels einer Map<Figur, String> die intern gehalten wird mit entsprechenden Werten. NONE -> "--"; PAWN_WHITE -> "BW"; ....
Und bei der Ausgabe wird eine Methode aufgerufen, die dann lediglich ein return ausgabeMap.get(figur); macht.

Das einfach nur ganz am Rand eine Überlegung, wie ich es handhaben würde.
 
Wenn man das Damebrett sieht, dann hat jedes Feld eine Figur und die kann ein Element einer Enum sein:
NONE, PAWN_BLACK, PAWN_WHITE, QUEEN_BLACK, QUEEN_WHITE.
dann hast du aber alles doppelt

er hat ja schon ein enum farbe dh er braucht ( um zumindest den string parameter weg zu bekommen der auch doppelt gemoppelt ist )
ein figuren enum
Java:
enum Figur{
    Bauer,Springer
}
dh in seiner figur wäre dann
farbe + figur enums wert eindeutig zuzuordnen
dann hast halt Farbe.Weiss + Figur.Bauer drinnen gespeichert

o eine ähnliche methode habe ich schon bereits ich möchte aber auch das irgentwas in der konsole ausgeben wird für das das Feld figur null hat .
naja das ist ja nur die überprüfugn ob überhaupt eine figur drauf ist

die benutzung wäre so ungefähr in der Feld klasse
Java:
public String contentToString(){
    if(istBesetzt()){
        return "Figur => "+this.figur;
    }else{
        return "Figur => leer";
    }
}
ZUSÄTZLICH
gibt es "injection" dh du übergibst gleich ein fertiges objekt zb:
deine bauern klasse erzeugt ein koordinaten objekt was man folgender maßen lösen könnte
Java:
Bauer(Koordinaten koordinaten, Farbe farbe, String typ){
    this.position = koordinaten;
    ....
das mit "i und j" zugänglich war so gemeint gibts einen getter für die koordinaten? somit könntest du zb irgendwo so eine methode einbauen... ist halt wie willst ud umgehen mit den koordinaten UNGEDGINGT brauchst du es nicht!

ZUM BEISPIEL
du hast eine koordinaten klasse und da machst du so ne methode rein
Java:
public static Koordinaten forward(Farbe farbe)
{
    if(farbe == farbe.Weiss)
    {
        return new Koordinaten(0,1);
    }
    else {
        return new Koordinaten(0,-1);
    }
}
public Koordinaten add(Koordinaten koord){
new Koordinaten( this.x + koord.x, this.y +koord.y);
}
der bauer könnte bei einer bewegung dann folgendes machen
Java:
public ... move(){
    return this.position.add(Koordinaten.forward(this.farbe));
}
somit würde ein bauer als "möglichen move" ausgeben
wenn er auf koordinate ( 3 , 5 ) steht und weiss ist
würde sowas raus kommen kommen als "move ergebnis" und zwar die kordinate ( 3, 6 )


ich würde in deinem fall sogar mal vererbung durchziehen bei deiner figur
zb
Java:
public BaseFigur{
    protected Farbe farbe;
    protected Koordinaten koordinaten;
   
    // den setter brauchst du sowieso falls du mal ne figur bewegt hast, musst ja position aktualisieren
    public void setKoordinaten(Koordianten koordinaten){
        this.koordinaten = koordinaten;
    }
}

das ist ja das was IMMER da sein muss bei egal welcher figur das könnte man schon raus ziehen, deine Klasse Figur erbt halt dann von BaseFigur

was hier zusätzlich zu erwähnen ist ist dass "protected" das ding sichtbar macht bei vererbung und da du ja vererbung machst ( hast ja deinen bauer der von figur erbt... und figur von basefigur) macht es sinn manche methoden und attribute für die unterklassen sichtbar zu machen

zusatz 2:
dass die figur UND das spielfeld weis wo was wie koordinaten mäßig ist IST NICHT SCHLIMM, Unity ( game engine ) hat das genau so, die szene weis alle koordinaten und jedes spiel objekt weis auch seine koordinaten... du musst halt nur gut damit umgehen

( hier wäre observer pattern angebracht um die "synchronisation" durchzusetzen aber ich möchte dir keinen bären aufbinden 🙂 )
 
Zuletzt bearbeitet:
dann hast du aber alles doppelt
Hier sind zwei Dinge wichtig:
a) Irgend etwas mit mehreren Klassen abzubilden, ist absolut in Ordnung. Natürlich kann er die Figuren so abbilden, wie ich das gezeigt habe. Unabhängig davon kann es auch die von angeführten Enums zusätzlich geben. Dann hat jede Figur hat auch och abfragbare Eigenschaften. Hier ist aber dann nicht automatisch "alles doppelt".

b) Es wurde nur eine Idee vorgestellt. Im Rahmen einer solchen Umsetzung hat man natürlich zu überlegen, was man vom alten Code noch beibehält und was nicht. Das wurde aber so tief nicht betrachtet.

c) Der Punkt mit Doppelt bezog sch doch ganz klar auf gespeicherte Daten:
Das wäre ja auch doppelt gespeichert
Das Problem ist doch offensichtlich:
this.damenbrett.get(i)[j].setFigur(new Bauer(i,j,Farbe.WEIS,"BW"));

Eine Figur hat also klar Koordinaten (i,j werden übergeben) und die Koordinaten einer Figur finden sich zugleich im Damenbrett (get(i)[j]). Du musst also aufpassen, dass Du nicht eine Figur mit Koordinaten x1,y1 hast die aber von einem Feld X2,Y2 referenziert wird i mit x1 != x2 und/oder y1 != y2. ==> Unnötige Komplexität.


Das einfach nur einmal um meinen Standpunkt zu verdeutlichen.
 
Das Problem ist doch offensichtlich:
this.damenbrett.get(i)[j].setFigur(new Bauer(i,j,Farbe.WEIS,"BW"));
mein "dann hast du alles auch doppelt" hat sich auf den string parameter "BW" = bauer weiss bezogen , hier hat man 2 mal die farbe drinnen, deswegen da das figuren enum

haben aneinander vorbei geredet... hatte auch noch was zu den koordinaten dazu editiert
 
noch kurze frage gibts es in der IDE auch eine Funktion mit der man einschalten kann, dass einem die methoden angezeigt werden wie wenn bei einem Objekt
bei z.b.
Java:
Figur f=Figur();
f.//methodennamen werden mir angezeigt
// aber bei
private boolean istXgrößerY(){
    return x>y;
}public void macheWas(){
    ist// hier werden mir nicht die Methodennamen angezeigt kann man das irgentwie anschalten in eclipse
}
 
noch kurze frage gibts es in der IDE auch eine Funktion mit der man einschalten kann, dass einem die methoden angezeigt werden wie wenn bei einem Objekt
bei z.b.
Java:
Figur f=Figur();
f.//methodennamen werden mir angezeigt
// aber bei
private boolean istXgrößerY(){
    return x>y;
}public void macheWas(){
    ist// hier werden mir nicht die Methodennamen angezeigt kann man das irgentwie anschalten in eclipse
}
drück mal einfach ctrl + space an der Stelle. Das ist ein gängiger Standard.
 

Zurück
Oben