it-swarm.com.de

Aufruf von equals auf String-Literal

Ich habe gerade meinen Code ein wenig aufgeräumt und es gab dieses Stück:

String saving = getValue();
if(saving != null && saving.equals("true")){
   // do something
}

Dann dachte ich daran, es andersherum zu machen, um die Überprüfung auf null zu beseitigen:

if("true".equals(saving)){
   // do something
}

Es funktioniert definitiv, aber ist das sicher um dies zu tun? Ich meine, String-Literale werden in einem gemeinsamen Pool gespeichert, während das von new erstellte String-Objekt auf dem Heap liegt. Aber auch Strings im konstanten Pool sind Objekte, oder?

Trotzdem scheint es nicht das Richtige zu sein, auch wenn der Code dadurch kürzer wird.

22
Kuba Spatny

Dies ist sicher - und wie Sie gesehen haben, eine gute Möglichkeit, Nullzeiger zu vermeiden.

Sie erwähnen die Verwendung von new für Strings. Viele statische Java-Analysetools für Java-Codes empfehlen immer, Literale über new String("foo"); zu verwenden.

Bearbeiten:

Wenn Sie möchten, können Sie sogar Folgendes verwenden:

if (Boolean.valueOf(saving)) {
    ...
}

Gemäß docs gibt das Übergeben von nullfalse zurück.

22
jakson

Nur um sicherzustellen, dass auf diese Frage völlig ausgewogene Antworten gegeben werden, möchte ich eine andere Meinung äußern.

Ich denke, dieser Mechanismus ist dumm.

Wenn Sie einen null haben, sollten Sie es wissen, sobald es passiert. Wenn Sie es ausblenden, wird die Erkennung nur verschoben. Wenn null keine Ausnahme ist, ersetzen Sie sie durch etwas anderes.

Wenn Sie diesen Ansatz anwenden, wird Ihr Code durch das, was defensive Programmierengenannt wird, verstärkt, wobei Ihre Fehler entdeckt werden so bald wie möglichund nicht vertuscht werden, bis alles zerbricht.

Zusammenfassend ist NullPointerException Ihr Freund. Sie sollten es verwenden, um Fehler in Ihrem Code zu finden. Es ist sehreasy, ein Empty -Objekt wie Collections.emptySet() zu verwenden, wenn Sie festgestellt haben, dass null keine Ausnahme ist.

Wenn Sie die Yoda-Technik aus Gewohnheit verwenden, werden Fehler, die Sie nicht verbergen wollen, unvermeidlich verborgen. Wenn nichtverwendet wird, werden Fehler viel früher aufgedeckt. Für mich ist das ein ausreichendes Argument, um es nicht zu verwenden - immer.

Für mich - mit

if(saving != null && saving.equals("true")){

bedeutet, dass ich tatsächlich zulassen möchte, dass savingsnull ist und dass dies eine akzeptable Situation ist - verwenden

if("true".equals(saving)){

verbirgt bloß diese vorsätzliche Wahl in einer Weise, die zur schlechten Angewohnheit werden könnte.

21
OldCurmudgeon

Es heißt Yoda-Bedingungen (eine Konstante vor einer Variablen in einem Vergleich setzen) kann als schlechte Praxis betrachtet werden, vielleicht für jemanden, der weniger lesbar ist (wie ich). 

Durch die Verwendung der yoda-Bedingung wird der Code jedoch manchmal "verständlicher". -> Sie müssen keine zusätzliche Nullprüfung vor dem Code einfügen, und er unterscheidet den Codeblock effizient von Fällen, in denen Null stark verboten ist.

8
Simon Dorociak

Ich stimme einigen Antworten nicht zu. Manchmal möchten Sie do wissen, ob Ihre Variable null ist. Dies kann ein Hinweis darauf sein, dass in Ihrem Code etwas nicht stimmt, und Sie möchten möglicherweise Ihre Logik überdenken. 

Ich mag es nicht, if("someString".equals(myString)); zu tun, weil ich do wissen möchte, ob myStringnull ist und vielleicht damit umgeht oder meine Logik ändert, um Situationen wie diese zu vermeiden.

Stellen Sie sich vor, Sie haben ein Array von Objekten, das aufgrund eines Fehlers falsch berechnet wurde:

myStrings = {..., ..., null, null, ...};

Dann möchten Sie einige Operationen an objects des Arrays durchführen, und Sie haben:

if("myString".equals(myObjArray[i])) { ... } 

Sie erhalten nicht NullPointerException und denken, dass Sie die Operation für alle objects im Array ausgeführt haben. Sie werden nie wissen, dass Sie sich falsch berechnet haben, weil Sie die Ausnahme "versteckt" haben. Wenn Sie dies getan haben:

if(myObjArray[i].equals("myString")) { ... } 

Sie erhalten einNPEund Sie wissen, dass im Array etwas nicht in Ordnung ist. Sie möchten das Problem beheben oder es anders behandeln.

8
Maroun
if("true".equals(saving)){
   // do something
}

Dies ist sehr sicher und eine gute Praxis. Die Zeichenfolge "true" wird niemals null sein. Sie werden Ihren String also niemals mit null vergleichen. Dieser Code ist vollkommen in Ordnung

5
k4sia

Das Format des ersten Buchstabens vermeidet die potenzielle NPE und ist für "literal".equals(null) immer falsch.

Dies liegt daran, dass ein "literaler" Ausdruck always zu einem String-Objekt ausgewertet wird (und daher niemals null ist), und String.equals(obj) prüft, ob das other object eine Null ist (über asinstanceof). Ein Objekt ist ein Objekt - keine Sorge über den "Haufen".

Es ist empfehlenswert, einen Null-Guard in einer equals-Implementierung zu haben da null.equals(null) ist nicht zulässig: "Die equals-Methode implementiert eine Äquivalenzrelation auf Nicht-Null Objektreferenzen"

Hier ist der String.equals der Quell (für OpenJDK):

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        // ..
    }
    return false;
}
4
user2864740

Sorry, aber ich kann dem nicht zustimmen. 

Wenn Sie die Konstante zuerst verwenden, unterstützen Sie Strukturen, die Programmierfehler verschleiern. Und man sollte auch nur Code produzieren 

  1. funktionalität hinzufügen,
  2. programmierfehler beheben
  3. oder versuchen, Strukturen zu unterstützen, um Programmierfehler zu vermeiden (wie Entwurfsmuster).

Außerdem haben Sie eine schwache Behauptung über die Variable. Der folgende Code muss immer auch nach Nullwerten suchen. 

Wenn Sie mit Nullwerten aus anderen Modulen arbeiten müssen, müssen Sie sie so früh wie möglich in Ihrem Domänenmodell in richtigen Repräsentationen abbilden. 

Vermeiden Sie in Ihrem eigenen Code den Parameter null oder den Rückgabewert, sodass keine Nullprüfungen mehr erforderlich sind, einschließlich des vorgeschlagenen Codes. 

In diesem Thema geht es also mehr darum, Null zu vermeiden, als es zu akzeptieren, um Ihren Code zu erobern.

2
oopexpert
if ("true".equals(saving))

ist perfekt "sparen" und wird von Dummy-Produkten als SonarLint und allen anderen Beratern empfohlen, die diese "gut" denkende Regel festlegen, die Ihren Chef verlangt, dass Sie folgen.

Ich sage dumm und meine Erklärung ist die folgende.

Was passiert, wenn Sie folgenden Code haben?

if (!saving.equals("true"))
    {
    if (saving.length() > 10)
        {
        // do something
        }
    }

Sie können den folgenden empfohlenen Code verwenden 

if (!"true".equals(saving))
    {
    if (saving.length() > 10)
        {
        // do something
        }
    }

Wenn Ihr Code jedoch in der Produktion implementiert wird, stürzt das Programm bei der Funktion length() ab, wenn das Speichern der Variablen nicht initialisiert wurde und NULL enthält. 

Sie müssen Ihren Code ändern, um NullPointerException in der Funktion equals() zu vermeiden, aber Ihr Programm gibt eine andere NullPointerException in der Funktion length() zurück!

Die gute Reaktion besteht darin, nicht mehr mit dem String-Literal-Tipp zu arbeiten und den Code zu analysieren, um eine perfekte Lösung zu finden (siehe folgendes Beispiel).

if (saving != null)
    {
    if (!saving.equals("true"))
        {
        if (saving.length() > 10)
            {
            // do something
            }
        }
    }

oder

if (saving == null) saving = "";

if (!saving.equals("true"))
    {
    if (saving.length() > 10)
        {
        // do something
        }
    }

Ist vielleicht ausführlich, aber wenn Sie Java zur Programmierung verwenden, ist dies der Preis, den Sie bezahlen müssen.

Die Verwendung der String-Literal-Methode equals () zur Vermeidung von NullPointerException hat die folgenden Nachteile

  1. die Lösung ist schwierig
  2. der Code ist für den Menschen natürlich nicht lesbar
  3. gleichheit wird nicht abstürzen, aber ein anderer Teil des Programms wird abstürzen
  4. code wird schnell schwer lesbar, wenn diese Tipps für die Funktionen lower () und größer () verwendet werden (Beispiel: if ('USA'.greater (sCode)))
  5. einen falschen Eindruck erwecken, dass der Code sicher ist
1
schlebe

Nicht nur sicher, sondern es ist auch ein bevorzugter Wegzur Lösung dieses Problems).

0
Marcin Szymczak