Nach einer Diskussion mit einigen meiner Kollegen habe ich eine „philosophische“ Frage dazu, wie der char-Datentyp in Java gemäß den Best Practices behandelt wird.
Angenommen, ein einfaches Szenario (dies ist offensichtlich nur ein sehr einfaches Beispiel, um meiner Frage eine Übungsbedeutung zu geben) , bei dem Sie bei Eingabe eines Strings die Anzahl der darin enthaltenen numerischen Zeichen zählen müssen.
Dies sind die 2 möglichen Lösungen:
1)
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) >= 48 && s.charAt(i) <= 57) {
n++;
}
}
2)
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) >= '0' && s.charAt(i) <= '9' ) {
n++;
}
}
Welche der beiden Methoden ist "sauberer" und entspricht den bewährten Java-Methoden?
VK_
Konstanten, die Sie verwenden sollen. Zweitens ist die Verwendung von Zeichencodes besser als die Verwendung von Zeichen. @Brandin Es heißt CodierungspraktikenVK_*
Konstanten entsprechen Schlüsseln, nicht Zeichen .Antworten:
Beide sind schrecklich, aber der erste ist schrecklicher.
Beide ignorieren Javas eingebaute Fähigkeit, zu entscheiden, welche Zeichen "numerisch" sind (über Methoden in
Character
). Aber der erste nicht ignoriert nur die Unicode - Natur von Strings, unter der Annahme , dass es nur 0123456789 sein kann, ist es auch verschleiert auch diese ungültig Argumentation von Zeichencodes verwenden , die Sinn machen nur , wenn Sie etwas über die Geschichte der Zeichenkodierungen kennen.quelle
matches("[0-9]+")
, anstatt den historisch motivierten Bereichstrick auszunutzen.Weder. Lassen Sie sich von Javas eingebauter Charakterklasse helfen.
Es gibt ein paar mehr Zeichenbereiche als die ASCII-Ziffern, die als Ziffern gelten, und keines der von Ihnen veröffentlichten Beispiele zählt sie. Die JavaDoc für
Character.isDigit()
Listen dieser Zeichenbereiche als gültige Ziffern zu sein:Character.isDigit()
Davon abgesehen sollte man auch mit dieser Liste delegieren . Wenn neue Unicode-Ebenen gefüllt werden, wird der Java-Code aktualisiert. Ein Upgrade der JVM könnte dazu führen, dass alter Code nahtlos mit neuen Ziffern funktioniert. Es ist auch TROCKEN : Durch Lokalisieren des Codes "Ist dies eine Ziffer?" An einer Stelle, auf die an anderer Stelle verwiesen wird, können die negativen Aspekte der Codeduplizierung (dh Fehler) vermieden werden. Beachten Sie zum Schluss die letzte Zeile: Diese Liste ist nicht vollständig, und es gibt andere Ziffern.Persönlich würde ich lieber an die Java-Kernbibliotheken delegieren und meine Zeit für produktivere Aufgaben verwenden, als "herauszufinden, was eine Ziffer ist".
Die einzige Ausnahme von dieser Regel ist, wenn Sie wirklich auf die wörtlichen ASCII-Ziffern und nicht auf andere Ziffern testen müssen . Wenn Sie beispielsweise einen Stream analysieren und nur ASCII-Ziffern (im Gegensatz zu anderen Ziffern) eine spezielle Bedeutung haben, ist die Verwendung nicht sinnvoll
Character.isDigit()
.In diesem Fall würde ich z. B. eine andere Methode schreiben
MyClass.isAsciiDigit()
und die Logik dort einfügen. Sie erhalten die gleichen Vorteile der Wiederverwendung von Code, der Name ist klar, was überprüft wird, und die Logik ist korrekt.quelle
Wenn Sie jemals eine Anwendung in C schreiben, die EBCDIC als Basiszeichensatz verwendet und ASCII-Zeichen verarbeiten muss, verwenden Sie
48
und57
. Machst du das Ich glaube nichtÜber die Verwendung
isDigit()
: es kommt darauf an. Schreiben Sie einen JSON-Parser? Nur0
um9
als Ziffern akzeptiert zu werden, also nicht verwendenisDigit()
, auf>= '0'
und prüfen<= '9'
. Verarbeiten Sie Benutzereingaben? Verwenden SieisDigit()
, solange der Rest Ihres Codes tatsächlich mit der Zeichenfolge umgehen und sie korrekt in eine Zahl umwandeln kann.quelle
Das zweite Beispiel ist eindeutig überlegen. Die Bedeutung des zweiten Beispiels wird beim Betrachten des Codes sofort deutlich. Die Bedeutung des ersten Beispiels ist nur dann offensichtlich, wenn Sie die gesamte ASCII-Tabelle in Ihrem Kopf gespeichert haben.
Sie sollten zwischen der Suche nach einem bestimmten Zeichen und der Suche nach einem Bereich oder einer Klasse von Zeichen unterscheiden.
1) Überprüfung auf ein bestimmtes Zeichen.
Verwenden Sie für gewöhnliche Zeichen das Zeichenliteral, z
if(ch=='z')...
. Wenn Sie nach Sonderzeichen wie Tabulator oder Zeilenumbruch suchen, sollten Sie die Escape-Zeichen wie verwendenif (ch=='\n')...
. Wenn das Zeichen, nach dem Sie suchen, ungewöhnlich ist (z. B. auf einer Standardtastatur nicht sofort erkennbar oder nicht verfügbar), verwenden Sie möglicherweise einen Hex-Zeichencode anstelle des Literalzeichens. Da ein Hex-Code ein "magischer Wert" ist, würden Sie ihn in eine Konstante extrahieren und dokumentieren:Hex-Codes sind die Standardmethode zur Angabe von Zeichencodes.
2) Prüfen auf eine Zeichenklasse oder einen Zeichenbereich
Sie sollten dies wirklich nicht direkt im Anwendungscode tun, sondern in einer separaten Klasse einschließen, die sich nur mit der Klassifizierung von Zeichen befasst. Und Sie sollten hiervon abweichen, da für diesen Zweck bereits Bibliotheken existieren und die Klassifizierung von Zeichen in der Regel komplexer ist als Sie denken, zumindest wenn Sie Zeichen außerhalb des ASCII-Bereichs berücksichtigen.
Wenn Sie sich nur um Zeichen im ASCII-Bereich kümmern, können Sie in dieser Bibliothek Zeichenliterale verwenden, andernfalls würden Sie wahrscheinlich Hex-Literale verwenden. Wenn Sie sich den Quellcode für die in Java integrierte Zeichenbibliothek ansehen, bezieht sich dieser auch auf Zeichenwerte und -bereiche mit Hexadezimalzeichen, da diese im Unicode-Standard so angegeben sind.
quelle
'\x2603'
hexadezimaler Schreibweise zu schreiben, um zu verdeutlichen, dass Sie den Wert für ein Zeichen mit hexadezimaler Codierung und nicht nur mit einer Zufallszahl testen.Es ist immer besser zu verwenden,
c >= '0'
dac >= 48
Sie c in ASCII-Code konvertieren müssen.quelle
Reguläre Ausdrücke ( RegEx s) haben eine bestimmte Zeichenklasse für Ziffern -
\d
-, mit der Sie beliebige andere Zeichen aus Ihrer Zeichenfolge entfernen können. Die Länge der resultierenden Zeichenfolge entspricht dem gewünschten Wert.Beachten Sie jedoch, dass RegEx-Systeme rechenintensiver sind als die anderen vorgeschlagenen Lösungen, weshalb sie nicht generell bevorzugt werden sollten .
quelle