Else if return


#1
    return Color.RED;
} else {
    return Color.GREEN;
}

-> Warnung: Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally.

aber

    return Color.RED;
} else if (condition2) {
    return Color.YELLOW;
} else {
    return Color.GREEN;
}

oder auch nur

    return Color.RED;
} else if (condition2) {
    return Color.YELLOW;
}

-> keine Warnung, wobei genauso else wegfallen könnten

https://bugs.eclipse.org/bugs/show_bug.cgi?id=61430
scheint bekannt und so gewollt, Stand 2004, wobei nur auf drittes Beispiel bezogen, nicht auf das ebenso nicht angemeckerte reine else im zweiten Beispiel

sind dazu gute Gründe bekannt?


#2

Für das letzte ist es eigentlich klar: Da muss ja noch ein anderes return stehen. Da ist nichts überflüssig. (Auch weil dort ja else if (incrementSomeCounterAndReturnWhetherItIsGreaterThanTen()) - also irgendwas mit Seiteneffekten - drinstehen könnte). Der zweite Fall leuchtet mir aber gerade auch nicht ein.


#3

das if sollte beim dritten Beispiel schon bleiben, nur das else davor verzichtbar
->

    return Color.RED;
}
if (condition2) {
    return Color.YELLOW;
}

genauso könnte im zweiten Beispiel das else if zum if werden und das finale else weg

Kleinigkeiten, aber nicht viel anders als der Grundzweck dieser Warnung


#4

Darf ich als erstes eigentlich überhaupt hinterfragen wofür die Warnung gut ist.

Warum sollte überhaupt vor einem else (mit return) gewarnt werden?

Gerade das erste Konstrukt verwende ich regelmäßig und eigentlich genau das weglassen des else (und nur return zuschreiben) empfinde ich als unsauber.


#5

Moin,

das heißt doch nichts anderes, als dass man es besser so schreibt:

if (condition1) 
{
        return Color.RED;
}
return Color.GREEN;

EDIT: Wenn condition1, dann return irgendwas, in ALLEN ANDEREN Fällen weitermachen. Das ist genauso sauber, und es wird nur davor gewarnt, dass das ELSE hier flüssiger als flüssig ist :slight_smile:

Gruß Klaus


#6

Auch auf SO gab es schon solche Diskussionen.

Konsens, es kommt der gleiche Byte-Code heraus.

Warum überhaupt die Warnung?
Konsistenz, sofern die Warnung in sich konsistent wäre.

Beispiel Versionskontrolle. Wenn jemand einen anderen Formatter nutzt und diesen auf eine Klasse anwendet, dann können sich Versionskontrollsysteme schwer tun die tatsächlichen Änderung zu verdeutlichen. Und dann gibt es eben noch so Oldschooltypen die eben auch Warnings für solche Dinge heranziehen und dann keine Commits mit Warnings zulassen. Somit kommt auch niemand auf die Idee den Code in if-return-else-return umzuändern.


#7

Wenn jmd das return statement entfernt wird ein komplett falsches Verhalten ausgelöst das nur mit zeitintensivem Debugging gelöst wird.
Der Code im TO ist für mich idiotensicher. Damit rotzt der Chinese den Code auch nicht mit StackOverflow Copy/Paste kaputt.


#8

Ich schreibe solche Passagen genau so, wie es @vfl_freak gezeigt hat. Das ist ebenso logisch. Mit einem return wird die Methode verlassen, was danach im Code steht, wird daher nicht mehr ausgeführt.
Wenn eine Methode einen Rückgabewert ausgibt, muss immer sicher gestellt sein, dass es ein return gibt. Bei der Passage, die @SlaterB eingangs gezeigt hat, ist das nicht sicher. Damit das nicht versehentlich übersehen wird, wird wohle diese Warnung ausgegeben.


#9

Damit nicht der falsche Eindruck entsteht, mir war sehr wohl klar, dass die Warnung diese Schreibweise bevorzugt.

        return Color.RED;
}
return Color.GREEN;```

Aber gerade die wörtliche Aussage:
Wenn condition1 wahr ist gib Rot zurück ansonsten Grün 
entspricht für mich 
```if (condition1) {
        return Color.RED;
}else{
       return Color.GREEN;
}```

#10

[QUOTE=L-ectron-X]
Wenn eine Methode einen Rückgabewert ausgibt, muss immer sicher gestellt sein, dass es ein return gibt. Bei der Passage, die @SlaterB eingangs gezeigt hat, ist das nicht sicher. Damit das nicht versehentlich übersehen wird, wird wohle diese Warnung ausgegeben.[/QUOTE]

ganz so kritisch steht es technisch zumindest nicht, die Variante mit dem else kompiliert, es ist nur eine einschaltbare Eclipse-Warnung,
Java ist mächtig genug es mit if + else zu schaffen,
und wenn man etwas am Code ändert so dass return nicht in allen Fällen garantiert bekommt man eh dann einen wirklichen Compilerfehler, falsch machen kann man es kaum

[QUOTE=TMII;140162]Wenn jmd das return statement entfernt wird ein komplett falsches Verhalten ausgelöst das nur mit zeitintensivem Debugging gelöst wird.
Der Code im TO ist für mich idiotensicher. Damit rotzt der Chinese den Code auch nicht mit StackOverflow Copy/Paste kaputt.[/QUOTE]

welcher Unterschied sollte in den Varianten beim Entfernen des return bestehen,
in einem Fall ein leeres else und das wäre leichter zu finden? hmm…


gegen die Bevorzugung von else an sich ist nicht viel zu sagen, außer dass es gar nicht unbedingt zur Debatte stand :wink:
aber wenn sonst nicht weiter zu klären warum Eclipse die Warnung nur selten bietet dann ja auch noch interessant,

für mich ist es ein unterschiedliches Sprachmittel für strukturelle Deutlichkeit,
if mit else läßt direkt erkennen dass kein Abbruch, dass es danach noch zwingend weitergeht (spätes edit: dass kein zwingender Abbruch, dass es danach noch weitergehen kann)

schwierig wird es mit if + else auch falls mehrere Abbruchgründe und noch Schritte dazwischen stehen, die ein else if verbieten,
also

    return Color.RED;
} else {
   prepareFor2;
   if (condition2) {
       return Color.YELLOW;
   } else {
       return Color.GREEN;
   }
}

aber wenn man idealerweise kurze Methoden hat kommt es freilich eh nie zu sowas :wink:
falls doch, dann wäre es derart verschachtelt immer noch zu bevorzugen, weil auch hier deutlich?

    return Color.RED;
} 
prepareFor2;
if (condition2) {
   return Color.YELLOW;
}
return Color.GREEN;

ist die Alternative, die Methode als Fluss von Befehlen auf niedrigster Einrückungsstufe,
ab und zu von einem if als Abzweigung zum Abbuch/ return unterbrochen, falls nicht benutzt, dann im Fluss weiter


#11

Moin,
ok, das Eingangsbeispiel war auch recht simpel …
Also auch hier finde ich diese Schreibweise

if (condition1) 
{
    return Color.RED;
}
prepareFor2;
if (condition2) 
{
   return Color.YELLOW;
}
return Color.GREEN;

deutlich übersichtlicher, weil man mehr oder weniger auf den ersten Blick mögliche Abläufe/Ausgaben erfassen kann!
Und je komplexer die Struktur rsp. Verschachtelung, desto lesbarer wird es IMHO !!

Das Ganz erinnert mich ein wenig an Diskussionen der Art:

boolean doSomething = true;

// entweder
if( true == doSomething ) //...

// oder doch besser
if( doSomething )  //...

Ich habe hier bislang noch kein (sinnvolles) Argument gelesen, warum ich ein Statement (hier das ‘else’) nutzen sollte, wenn ich es nicht zwingend muss!
Code soll doch lesbar und nachvollziehbar sein … :slight_smile:

Gruß Klaus


#12

man denke nur an Methodenparameter a la

    {
        if (a == null)
            throw new IllegalArgumentException("a is null");
        else if (b == null)
            throw new IllegalArgumentException("b is null");
        else
        {
            System.out.println(a.equals(b));
        }
    }

mit Exceptions ist es dasselbe wie mit return, Eclipse warnt hier nicht, beim einfachen else schon…,

jedenfalls wäre es je nach Stil (derartige Prüfungen kann man vielleicht auch für sich ablehnen)
mit solchen Prüfungen zu Beginn einer Methode arg unschön, den Hauptteil der Methode in ein else zu stecken…,
lieber

    {
        // Vorarbeit
        if (a == null) throw new IllegalArgumentException("a is null");
        if (b == null) throw new IllegalArgumentException("b is null");

        // nun gehts los
        System.out.println(a.equals(b));
    }

#13

[QUOTE=SlaterB]man denke nur an Methodenparameter a la

    {
        if (a == null)
            throw new IllegalArgumentException("a is null");
        else if (b == null)
            throw new IllegalArgumentException("b is null");
        else
        {
            System.out.println(a.equals(b));
        }
    }

mit Exceptions ist es dasselbe wie mit return, Eclipse warnt hier nicht, beim einfachen else schon…,
[/QUOTE]
nun ja, obwohl das selbst in der ‘Insel’ so gemacht/empfohlen wird …
Rheinwerk Computing :: Java ist auch eine Insel – 6.5 Auslösen eigener Exceptions

[QUOTE=SlaterB;140186]
jedenfalls wäre es je nach Stil (derartige Prüfungen kann man vielleicht auch für sich ablehnen)
mit solchen Prüfungen zu Beginn einer Methode arg unschön, den Hauptteil der Methode in ein else zu stecken…,
lieber

    {
        // Vorarbeit
        if (a == null) throw new IllegalArgumentException("a is null");
        if (b == null) throw new IllegalArgumentException("b is null");

        // nun gehts los
        System.out.println(a.equals(b));
    }
```[/QUOTE]
würde ich eh' dadurch lösen, dass ich ggf. die Methode gar nicht erst aufrufe:

// irgendwo
if( a != null) && (b != null) )
{
todo( a, b );
}
else if( null == a )
{
throw new IllegalArgumentException(“a is null”);
}
else if( null == b )
{
throw new IllegalArgumentException(“b is null”);
}
// irgendwas anderes


Gruß Klaus

#14

[QUOTE=vfl_freak;140188]nun ja, obwohl das selbst in der ‘Insel’ so gemacht/empfohlen wird …
Rheinwerk Computing :: Java ist auch eine Insel – 6.5 Auslösen eigener Exceptions
[/quote]
klingt als würde in der Insel empfohlen es mit else zu machen, aber auf der verlinkten Seite kein einziges else zu finden,

dass eine Exception am Anfang der Methode ein zumindest denkbares Mittel ist, ist klar,
aber best(angenommen)e Stile richten sich nicht unbedingt nach der Insel :wink: , ich weiche gewiss auch immer ab wenn es mir passt


würde ich eh’ dadurch lösen, dass ich ggf. die Methode gar nicht erst aufrufe:

// irgendwo
if( a != null) && (b != null) )
{
    todo( a, b );
}
else if( null == a )
{
    throw new IllegalArgumentException("a is null");
}
else if( null == b )
{
    throw new IllegalArgumentException("b is null");
}
// irgendwas anderes

puh, also da möchte ich nun auch wiederum widersprechen, bei potentiell tausenden Aufrufen? jeder andere soll selber prüfen?
das widerspricht doch dem Sinn einer Methode, dort Code zusammengefasst einmalig für viele andere

man stelle sich vor, jeder der folgende API-Methode nutzt, müsste selber entsprechend prüfen…

        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

nebenbei wiederum der Stil erkennbar, alles hinterm if in else verschachtelt wäre doch unschön,

deine Variante, so undenkbar auch beim Aufrufer auszuführen, hat übrigens auch das if und else, bewußt?
ließe sich doch wenn dann auch umformulieren zu

if( null == b ) throw new IllegalArgumentException("b is null");
todo( a, b );

wieso nicht so?

aber verrückt finde ich das so oder so, in einer Methode berechnet man doch normalerweise selber die Dinge, die dann an andere Methoden übergeben werden
oder hat jedenfalls ungefähre Vorstellungen, warum dann diese eigenen Variablen explizit auf null prüfen?..


#15

Wobei ich eben ein Unterscheidung mache was ich mit dem if- (else-) Konstrukt Aussagen möchte.

Im ersten Bsp will ich einen Rückgabewert auf Basis eines inputs (kurz und knapp)

if (isHighlight){
  return Color.RED;
}else{
  return Color.GREEN;
}

im anderen Fall, will ich z.B. nur den input zuerst auf Validität prüfen und dann einen aufwendigeren Code

if (isValidInput(input){
  return Color.RED;
}
  
//start parsing XML and find correct Color
// ...
return foundColor;

ich mache hier einen Unterschied daher für ein so kurzes Bsp finde ich es lesbarer mit einem explizitem else Block. in den Bsps mit Exceptions oder eben langen Code teil im (nicht vorhandenem) else - Block. würde ich auch die Variante ohne else bevorzugen. Durch das Weglassen des Else steckt für mich einen andere Intention dahinter und das drücke ich dann eben durch das weglassen aus.

Für mich Persönlich sind daher beide Varianten Gleichberechtigt (je nach Anwendungsfall die eine oder die andere) und die Warnung daher nutzlos und zum Glück anscheinend bei eclipse auch nicht standardmäßig angeschaltet.

Das erste Bsp im Eingangspost würde ich eigentlich immer mit else Zweig schreiben.
Just my two cents


#16

Mischung beider Stile kann man wiederum als noch schlimmer als entweder als das eine oder das andere ansehen, aber eben alles Ansichtssache :wink:

Code lebt nicht nur von fachlicher Bedeutung, auch Strukturierung/ Einrückung wichtig für sofortige optische Erkennungsprozesse, Einheitlichkeit dazu günstig

befolge ich freilich auch nicht überall, etwa Abkürzung

vs.

   throw new IllegalArgumentException("a is null");
}

zu schwer, darauf zu verzichten, auch wenn gegenüber mehrzeiligen ifs mit zwingend Klammern abweichend…


#17

moinsen,

ok, habe ich unglücklich ausgedrückt :sick:
Ich meinte ja das Beispiel bei 6.5.1 :wink:

ok ok, da hast Du natürlich Recht!
Das war jetzt auch eher beispielhaft gedacht!
Ich habe hier desöfteren Stellen, bei denen lediglich größere Codeblöcke in Methoden ausgelagert werden, die dann nur an einer Stelle aufgerufen werden.
Und da kann ich die Vorbedingungen ja ganz gut VOR Aufruf prüfen …

Weil es wohl doch zu früh mich ist :smiley:
Hast natürlich Recht … das ist (noch) eleganter :stuck_out_tongue_winking_eye:

Letztlich ist die Diskussion wohl auch rein akademisch, da es ja in vielen Firmen eigene StyleGuides gibtdie ggf. auch Derartiges regeln !

Gruß Klaus

*** Edit ***

[QUOTE=SlaterB;140193]Mischung beider Stile kann man wiederum als noch schlimmer als entweder als das eine oder das andere ansehen, aber eben alles Ansichtssache :wink:
Code lebt nicht nur von fachlicher Bedeutung, auch Strukturierung/ Einrückung wichtig für sofortige optische Erkennungsprozesse, Einheitlichkeit dazu günstig
zu schwer, darauf zu verzichten, auch wenn gegenüber mehrzeiligen ifs mit zwingend Klammern abweichend…[/QUOTE]
Richtig, wir klammern hier solche Fälle IMMER, andernfalls kommt es doch schnell mal zu Flüchtigkeitsfehlern …


#18

[quote=vfl_freak;140196]Ich habe hier desöfteren Stellen, bei denen lediglich größere Codeblöcke in Methoden ausgelagert werden, die dann nur an einer Stelle aufgerufen werden.
Und da kann ich die Vorbedingungen ja ganz gut VOR Aufruf prüfen …[/quote]
oder gar nicht prüfen wenn Code in einer (langen) Methode das auch nicht zwischendurch machen würde :wink:

die Prüfung ist ja vor allem bei API-Methoden (auch programmintern) die sich an beliebige Aufrufer richten,
mit unbekannten und deswegen ruhig zu prüfenden Stand von dort beim unbekannten Aufrufer


#19

Aus reiner Nickeligkeit möchte ich mal sagen: Ich finde euer aller Code häßlich. :playful:

Bei mir sähe die Methode grundsätzlich so aus:

    Color color;

    if( condition ) {
        color = Color.RED;
    } else {
        color = Color.GREEN;
    }

    return color;
}

Ggf. auch mit color = condition ? Color.RED : Color.GREEN;, aber sicher nicht mit returns mittendrin. Mag man als Kindergarten-Stil bezeichnen, hat sich aber (bislang) als vollkommen streßfrei erwiesen.
:popcorn:


#20

Auf den Hinweis, “nur ein return pro Methode” hatte ich schon gewartet. Ich finde das an sich nicht verkehrt, aber findet seine Grenze in solchen Fällen wie hier, oder auch

case 1: return "one";
case 2: return "two";
case 3: return "five";

oder bei “Watchdogs”, wie

Result compute(Input input) {
    if (input.isTrivial()) return Result.trivial();
    
    // 100 lines...
    return complexResult;
}