Heim >Java >javaLernprogramm >10 praktische, aber paranoide Java-Programmiertechniken
Nachdem Sie sich eine Zeit lang mit dem Codieren beschäftigt haben, werden Sie sich allmählich an diese Dinge gewöhnen. Denn, wissen Sie...
Alles kann schief gehen, ja, das passiert.
Aus diesem Grund übernehmen wir eine „defensive Programmierung“, die der Grund für einige paranoide Gewohnheiten ist. Im Folgenden sind die meiner persönlichen Meinung nach zehn nützlichsten, aber paranoidsten Java-Programmiertechniken aufgeführt. Werfen wir einen Blick darauf:
1. Setzen Sie den String-String an den Anfang
Um gelegentliche NullPointerException-Ausnahmen zu verhindern, setzen wir normalerweise String die linke Seite der Funktion equal(), um einen String-Vergleich zu implementieren, wie im folgenden Code gezeigt:
// Bad if (variable.equals("literal")) { ... } // Good if ("literal".equals(variable)) { ... }
Dies ist etwas, was Sie tun können, indem Sie einfach darüber nachdenken und den Ausdruck aus der Bad-Version von neu schreiben Wenn Sie den Code auf den Good-Versionscode umstellen, geht dazwischen nichts verloren. Unterschiedliche Meinungen sind willkommen...
2. Vertraue nicht der frühen JDK-API
In den frühen Tagen von Java war das Programmieren eine sehr schmerzhafte Sache. Diese APIs sind noch sehr unausgereift. Vielleicht sind Sie auf den folgenden Codeblock gestoßen:
String[] files = file.list(); // Watch out if (files != null) { for (int i = 0; i < files.length; i++) { ... } }
Sehen Sie paranoid aus? Vielleicht, aber siehe Javadoc:
Wenn dieser virtuelle Pfad kein Ordnerverzeichnis darstellt, gibt diese Methode null zurück. Andernfalls wird ein Array von Zeichenfolgen zurückgegeben, wobei jede Zeichenfolge eine Datei oder einen Ordner im Verzeichnis darstellt.
Ja, das stimmt. Wir können eine Bestätigung hinzufügen:
if (file.isDirectory()) { String[] files = file.list(); // Watch out if (files != null) { for (int i = 0; i < files.length; i++) { ... } } }
3. Glauben Sie nicht „-1“
Ich weiß, dass das paranoid ist, aber im Javadoc steht das eindeutig für String.indexOf(). Methode: Der Positionsindex des ersten Vorkommens des angegebenen Zeichens im Objekt. Wenn er -1 ist, bedeutet dies, dass das Zeichen nicht in der Zeichenfolge enthalten ist.
Die Verwendung von -1 ist also ein Kinderspiel, oder? Ich bin mir nicht sicher, schauen Sie sich bitte den folgenden Code an:
// Bad if (string.indexOf(character) != -1) { ... } // Good if (string.indexOf(character) >= 0) { ... }
Wer weiß. Vielleicht haben sie bis dahin die Codierung so geändert, dass bei Zeichenfolgen die Groß-/Kleinschreibung nicht beachtet wird, und vielleicht ist es eine bessere Möglichkeit, -2 zurückzugeben? Wer weiß.
4. Vermeiden Sie versehentliche Zuweisungen
Ja. Dies kann häufig vorkommen.
// Ooops if (variable = 5) { ... } // Better (because causes an error) if (5 = variable) { ... } // Intent (remember. Paranoid JavaScript: ===) if (5 === variable) { ... }
Sie können die Vergleichskonstante also auf der linken Seite platzieren, damit es nicht zu versehentlichen Zuordnungsfehlern kommt.
5. Überprüfen Sie Null und Länge
Solange Sie eine Sammlung, ein Array usw. haben, stellen Sie sicher, dass diese vorhanden und nicht leer sind.
// Bad if (array.length > 0) { ... } // Good if (array != null && array.length > 0) { ... }
Sie wissen nicht, woher diese Arrays kommen, vielleicht von einer früheren Version der JDK-API, wer weiß.
6. Alle Methoden sind endgültig.
Sie können mir Ihr Öffnungs-/Schließprinzip verraten, aber das ist alles Unsinn. Ich glaube Ihnen nicht (erbe alle Unterklassen meiner Elternklasse korrekt), und ich glaube mir selbst nicht (erbe versehentlich alle Unterklassen meiner Elternklasse). Daher sollten Methoden mit klarer Bedeutung unbedingt mit „final“ gekennzeichnet werden.
// Bad public void boom() { ... } // Good. Don't touch. public final void dontTouch() { ... }
7. Alle Variablen und Parameter sind endgültig.
Wie ich schon sagte. Ich traue mir selbst nicht zu (meine Werte nicht versehentlich zu überschreiben). Allerdings glaube ich meine nicht, weil…
…这就是为什么所有的变量和参数都是final的原因。
// Bad void input(String importantMessage) { String answer = "..."; answer = importantMessage = "LOL accident"; } // Good final void input(final String importantMessage) { final String answer = "..."; }
8.重载时不要相信泛型
是,它可以发生。你相信你写的超级好看的API,它很直观,随之而来的,一些用户谁只是将原始类型转换成Object类型,直到那该死的编译器停止发牢骚,并且突然他们会链接错误的方法,以为这是你的错误。
看下面的代码:
// Bad <T> void bad(T value) { bad(Collections.singletonList(value)); } <T> void bad(List<T> values) { ... } // Good final <T> void good(final T value) { if (value instanceof List) good((List<?>) value); else good(Collections.singletonList(value)); } final <T> void good(final List<T> values) { ... }
因为,你知道……你的用户,他们就像
// This library sucks @SuppressWarnings("all") Object t = (Object) (List) Arrays.asList("abc"); bad(t);
相信我。这一切我都看到过。包括下面的
这种偏执还是不错的。
9.总是在Switch语句的Default中抛出异常
Switch语句……它们其中一个可笑的语句我不知道该对它敬畏还是哭泣,但无论如何,既然我们坚持用switch,那我们不妨将它用得完美,看下面的代码:
// Bad switch (value) { case 1: foo(); break; case 2: bar(); break; } // Good switch (value) { case 1: foo(); break; case 2: bar(); break; default: throw new ThreadDeath("That'll teach them"); }
当value == 3时,将会出现无法找到的提示,而不会让人不知所谓。
10.Switch语句带花括号
事实上,switch是最邪恶的语句,像是一些喝醉了或者赌输了的人在写代码一样,看下面的例子:
// Bad, doesn't compile switch (value) { case 1: int j = 1; break; case 2: int j = 2; break; } // Good switch (value) { case 1: { final int j = 1; break; } case 2: { final int j = 2; break; } // Remember: default: throw new ThreadDeath("That'll teach them"); }
在switch语句中,每一个case语句的范围只有一行语句,事实上,这些case语句甚至不是真正的语句,他们就像goto语句中的跳转标记一样。
在switch语句中,每一个case语句的范围只有一行语句,事实上,这些case语句甚至不是真正的语句,他们就像goto语句中的跳转标记一样。
结论
偏执编程看起来似乎不可思议,有时,因为代码经常被证明是更详细一点,但并不是需求需要。你可能会想,“哦,这是绝不会发生的”,但正如我所说。经过20年左右的时间编程,你不希望只修复这些愚蠢的bug,因为编程语言是如此的陈旧的和有缺陷的。因为你知道…