leeres Array statt Null Pointer Exception ausgeben

SimonOsiris

Mitglied
Hallo, ich bräuchte wieder eure Hilfe.

Ich versuche folgende Aufgabenstellung zu lösen:

"Implementieren Sie die Methode static int[] addArrayValues(int[], int[]).

addArrayValues übernimmt zwei int-Arrays und liefert ein int-Array als Rückgabe. Die Methode soll den jeweils i-ten Wert der beiden übergebenen Arrays addieren und das Ergebnis an die i-te Stelle eines dritten Arrays speichern. Geben Sie dieses Array am Ende Ihrer Methode zurück.

Falls die übergebenen Arrays nicht dieselbe Länge haben oder mindestens eines davon null ist, soll ein leeres Array zurückgegeben werden."

Momentan sieht mein Code so aus:
Java:
public class Exercise {
    // TODO Put your method definition here

    public static void main(String[] args) {
        int[] array1 = null;
        int[] array2 = {5,4,3,2,1};
        if (array1 == null || array2 == null) {
            int [] leeresArray = {};
            for (int i = 0; i < leeresArray.length; i++)
            System.out.print(leeresArray[i]);
        }
        else if (array1.length != array2.length){
            int [] leeresArray = {};
            for (int i = 0; i < leeresArray.length; i++)
                System.out.print(leeresArray[i]);
        }
        else {
            addArrayValues(array1, array2);
        }
    }

    static int[] addArrayValues(int[] array1, int[] array2) {
            int[] lastArray = new int[array2.length];
            for (int i = 0; i < array1.length; i++) {

                lastArray[i] = array1[i] + array2[i];


            }


            return lastArray;
        }
    }

Höchstwahrscheinlich wieder unnötig kompliziert aber ich bin nicht draufgekommen wie es sich einfacher lösen lässt. Mein Problem hier ist dass eine oder mehrere Null Pointer Exceptions auftreten, was zu einem Laufzeitfehler führt. Es soll stattdessen aber sobald ein Array null ist einfach ein leeres Array ausgegeben werden.
Danke für eure Hilfe
 
Du machst hier irgendwas aber nichts davon entspricht der Aufgabe.
Die Überprüfung "Falls die übergebenen Arrays nicht dieselbe Länge haben oder mindestens eines davon null ist, soll ein leeres Array zurückgegeben werden." führst du nicht in "addArrayValues" durch, sondern vorher, bevor du die Methode überhaupt aufrufst.
 
Überlege dir mal, ob das irgend einen Sinn hat:
Java:
            int [] leeresArray = {};
            for (int i = 0; i < leeresArray.length; i++)
            System.out.print(leeresArray[i]);
 
Du vermischst - wie es viele tun - Logik und Ausgabe.
Die gesamte Aufgabe bezieht sich auf die zu schreibende Methode. Ob du irgendwas auf den Bildschirm ausgeben musst oder nicht, steht da nicht.

Fang mal damit an, dass deine Methode diese Zeile der Aufgabe umsetzt
"Falls die übergebenen Arrays nicht dieselbe Länge haben oder mindestens eines davon null ist, soll ein leeres Array zurückgegeben werden."

Edit: Wichtig (kann man nicht oft genug sagen): Es geht hierbei nicht um die Ausgabe am Bildschirm, sondern um den Rückgabewert der Methode
 
Verstehe, danke schon einmal für eure Antworten!
bevor du die Methode überhaupt aufrufst
Falls die übergebenen Arrays nicht dieselbe Länge haben oder mindestens eines davon null ist, soll ein leeres Array zurückgegeben werden.

Meint ihr in etwa so?
Java:
public static void main(String[] args) {
        int [] array1 = {5,5,5,5,5};
        int [] array2 = {5,4,3,2,1};
        addArrayValues(array1, array2);
    }


    static int[] addArrayValues(int[] array1, int[] array2) {
        if (array1.length != array2.length || array1 == null || array2 == null) {
            int[] emptyArray = {};
            return emptyArray;
        } else {
            int[] lastArray = new int[array2.length];
            for (int i = 0; i < array1.length; i++) {

                lastArray[i] = array1[i] + array2[i];


            }


            return lastArray;
        }
    }
}
 
Hier kommt es sofort zu einer NPE:
Java:
if (array1.length != array2.length || array1 == null || array2 == null) {
Du musst natürlich erst auf NULL testen und dann die Länge überprüfen.
 
Vielen Dank Oneixee5 für deine Hilfe!
Jetzt hat es funktioniert, ich wusste nicht dass ich zuerst auf null testen muss, aber es macht Sinn 🙂

Hier mein fertiger Code:
Java:
public static void main(String[] args) {
        int [] array1 = {5,5,5,5,5};
        int [] array2 = {5,4,3,2,1};
        addArrayValues(array1, array2);
    }


    static int[] addArrayValues(int[] array1, int[] array2) {
        if (array1 == null || array2 == null || array1.length != array2.length ) {
            int[] emptyArray = {};
            return emptyArray;
        } else {
            int[] lastArray = new int[array2.length];
            for (int i = 0; i < array1.length; i++) {

                lastArray[i] = array1[i] + array2[i];


            }


            return lastArray;
        }
    }
}
 
So ein Konstrukt macht keinen Sinn:
Java:
if ( ... ) {
    return <irgendwas>;
} else {
    return <irgendwas anderes>;
}
Richtig es das so:
Java:
if ( ... ) {
    return <irgendwas>;
}
return <irgendwas anderes>;
return - verlässt sofort die aktuelle Methode. Das ist auch in einem if-Block so. Daher ist es verwirrend und schlechter Stil ein 'else' anzubieten, es würde niemals ausgeführt.
 
Zeile 4: das zurückgebene Array einer Variablen zuweisen: int[] summen = addArrayValues(array1, array2);,
sonst ist es verloren.

Was Deinem Programm jetzt noch fehlt, ist eine Ausgabe. Dafür könntest Du eine zusätzliche Methode implementieren, die ein Array nach Deinem Gusto anzeigt.
static void ausgabeArray(int[] array) { ... <gebe das Array aus> }

alternativ gibt es die fertige Methode toString() aus der Klasse Arrays, die einen String zurück gibt, der alle Elemente des Arrays auflistet.
das könnte dann so aussehen. String ausgabe = Arrays.toString(array1); System.out.println(ausgabe);,
oder ganz kurz: System.out.println(Arrays.toString(addArrayValues(array1, array2)));

Um Arrays-Methoden zu benützen, musst Du erst die Klasse importieren mit import java.util.Arrays; in Zeile 0
 
Hallo, Marvin! Danke für deine Antwort, mit diesen Arrays.toString hab ich noch ein bisschen zu kämpfen weil ich nicht genau weiß wie das richtig eingesetzt wird. Zum Beispiel blicke ich bei dieser eigentlich einfachen Aufgabe auch nicht ganz durch:

"
Definieren Sie folgende Methoden und deren Übergabeparameter. Diese Methoden müssen keine Funktionalität bieten.

Achten Sie auf die korrekte Benennung der einzelnen Methoden sowie auf die Reihenfolge der Parameter.

  • Die Methode methodWithoutParameter ohne Parameter und ohne Rückgabewert
  • Die Methode methodInt mit einem Parameter (int) und ohne Rückgabewert
  • Die Methode methodIntArray mit einem Parameter (int[]) und ohne Rückgabewert
  • Die Methode methodCharIntArray mit zwei Parametern (char und int[]) und ohne Rückgabewert
  • Die Methode methodReturnChar mit zwei Parametern (int[] und char) und Rückgabewert (char)
  • Die Methode methodReturnArray mit zwei Parametern (char und int[]) und Rückgabewert (int[])
Geben Sie bei Methoden mit Rückgabewert einfach einen der übergebenen Parameter zurück.

Rufen Sie anschließend die beiden Methoden mit Rückgabeparametern in der main-Methode auf und geben Sie die zurückgegebenen Werte auf der Konsole aus. Verwenden Sie als Eingabeparameter die zur Verfügung gestellten Variablen.

Verwenden Sie das Schlüsselwort static in den Methodendeklarationen.

Tipp: Verwenden Sie die Methode Arrays.toString() um ein Array in einen String umzuwandeln."


Der Code den ich dazu geschrieben hab sieht so aus:
Java:
public static void main(String[] args) {
        int paramInt = 123;
        char paramChar = 'c';
        int[] paramIntArray = {1, 2, 3, 4, 5};

        // TODO Put your method calls here

        System.out.println(methodReturnChar(paramChar));
        System.out.println(Arrays.toString(methodReturnArray(paramIntArray)));


    }

    // TODO Put your method definitions here

    public static void methodWithoutParameter () {

    }

    public static void methodInt (int a){

    }
    public static void methodIntArray (int[] b){

    }
    public static void methodCharIntArray (char c,int[] d){

    }
    public static char  methodReturnChar (int [] paramIntArray,char paramChar){
        return paramChar;


    }
    public static int [] methodReturnArray (char paramChar, int [] paramIntArray) {

        return paramIntArray;

    }

}

Bei mir funktioniert das mit der Ausgabe aber noch nicht so ganz und ich blicke nicht genau durch warum.
 
Wenn man eine Methode mit ReturnWert aufruft, will man in der Regel den ReturnWert auch für etwas verwenden. Es ist gängige Praxis, diesen Wert in einer geeigneten Variable, einem Array oder einer Liste zu speichern. Man kann den RückgabeWert aber auch gleich als Parameter in einer (anderen) Methode weiter verwenden, ohne ihn vorher zu speichern.
Klassisches Beispiel: System.out.println(myObject.toString()); Hier wird zuerst die Methode "toString" von "myObject" aufgerufen, welche einen String zurück gibt. Dieser String ist dann der Parameter der Methode "println", welche den String auf der Konsole ausgibt.

Wenn also eine Methode ein int-Array zurück gibt, hast Du die Möglichkeit, das Array erst irgendwo (z.B. in einer Variablen des gleichen Typs) zu speichern, oder eben gleich weiter zu leiten an die nächste Methode, die diesen Typ als Parameter annimmt.
Da Arrays.toString(...) auch int-Arrays annimmt, kannst Du als Parameter auch einen Methodenaufruf in die Klammern schreiben, wenn Dieser Aufruf den entsprechenden Typ zurückgibt.
Und da Arrays.toString(...) einen String zurück gibt, kannst Du diesen Methodenaufruf als Parameter für eine weitere Methode verwenden, welche eben einen String als Parameter akzepiert.
Dann kommt mitunter so ein verschachtelter Aufruf wie
System.out.println( Arrays.toString( methodReturnArray(paramChar, iparamIntArray) ) ); zustande.
 
Zuletzt bearbeitet:
Bei mir funktioniert das mit der Ausgabe aber noch nicht so ganz und ich blicke nicht genau durch warum.
So blöd das klingen mag, aber um herauszufinden warum etwas nicht klappt, sind Fehlermeldungen und der vollständige Quelltext, hilfreich.

Bei deinem geposteten Quelltext fehlen die Klasse und evtl. Imports, von denen du min. "java.util.Arrays" haben solltest, wie Marvin schon schrieb.
Und wenn der Compiler eine Fehlermeldung ausgibt, dann ist das auch interessant zu wissen welche.
Ohne diese Informationen wird dir niemand zielgerichtet helfen können.
 
Hier:
Java:
        System.out.println(methodReturnChar(paramChar));
        System.out.println(Arrays.toString(methodReturnArray(paramIntArray)));
fehlt jeweils der 2. Parameter bei den Methodenaufrufen.
 
Danke für die ausführliche Erklärung Marvin!
Ich glaube das meiste davon verstehe ich.
Es ist gängige Praxis, diesen Wert in einer geeigneten Variable, einem Array oder einer Liste zu speichern
Speichert man den Wert dann meistens in der Methode oder beim Aufrufen in der main?

Bei deinem geposteten Quelltext fehlen die Klasse und evtl. Imports
Tut mir leid, das war alles dabei aber ich hab den Code gekürzt.

Hier fehlt jeweils der 2. Parameter bei den Methodenaufrufen.
Das war tatsächlich so kinderleicht dass ich mich jetzt dumm fühle. Danke für deinen Hinweis, ich habe außerdem nicht auf die richtige Reihenfolge der Parameter geachtet🤦‍♂️
 
Ah verstehe, wusste nicht dass das else hier sinnlos ist, aber macht Sinn. Danke für den Hinweis
Nein, das passt schon. Ist meiner Meinung nach sogar übersichtlicher, vor allem wenn man dann noch mehrere Bedingungen mit else if abfragt oder in den Blöcken noch mehr passiert als ein einfaches Return.
Schaut blöd aus, wenn ein Teil anders eingerückt ist als der Rest.

Letztendlich ist das nur persönliche Präferenz, ist beides gleich gut.

Was in so einem einfachen Fall auch geht, ist:
Java:
return (bedingung)
    ? <irgendwas>
    : <irgendwasanderes>;
 
Speichert man den Wert dann meistens in der Methode oder beim Aufrufen in der main?
Das kann nicht pauschal beantwortet werden. Hängt immer davon ab, wer/was alles diese Daten wann benötigt. Ihr arbeitet noch nocht objektorientiert. Noch ist alles statisch. das wird sich bald ändern und werden Instanzen von (selbst geschriebenen) Klassen erzeugt. Die haben dann Attribute, etc. Kurzum, viele, aber längst nicht alle, Returnwerte landen "in" Instanzattributen.
 
Nein, das passt schon. Ist meiner Meinung nach sogar übersichtlicher, vor allem wenn man dann noch mehrere Bedingungen mit else if abfragt oder in den Blöcken noch mehr passiert als ein einfaches Return.
Schaut blöd aus, wenn ein Teil anders eingerückt ist als der Rest.

Letztendlich ist das nur persönliche Präferenz, ist beides gleich gut.

Was in so einem einfachen Fall auch geht, ist:
Java:
return (bedingung)
    ? <irgendwas>
    : <irgendwasanderes>;
Return ist return - eine 'else' hinter return ist ein Code-Smell und nicht übersichtlicher. Vermutlich entfernt der Compiler das auch, falls es vorhanden ist.
 
Return ist return - eine 'else' hinter return ist ein Code-Smell und nicht übersichtlicher. Vermutlich entfernt der Compiler das auch, falls es vorhanden ist.
Welcher Code stinkt, liegt im Auge des Betrachters.
Begriffe wie "Code Smell" dienen nur dazu, die eigene Meinung als wichtiger darzustellen. Wenn der Compiler es eh entfernt, dann gibt es keinen Grund, es wegzulassen.
Du findest es nicht übersichtlicher ... ok, kann ich akzeptieren. Wenn es für dich übersichtlicher ohne else ist, dann verwende auch keines.

Wenn es abhängig von einer Bedingung 2 verschiedene Zustände gibt, dann verwende ich if-then-else, ich finde das übersichtlicher. Lieber hab ich eine saubere Struktur als mich damit brüsten zu können, weniger Code geschrieben zu haben.

Unterm Strich ist es komplett Jacke wie Hose (oder kommt jetzt die Anti-Pattern Keule?)

@SimonOsiris
Programmier auf die Art und Weise, von der du glaubst, dass du den Code in einem Jahr besser lesen kannst, wenn du dich nicht mehr daran erinnerst, was das Ganze eigentlich sollte.
 

Zurück
Oben