Heim  >  Artikel  >  Java  >  Zusammenfassung einiger häufiger Probleme bei der Java-Programmierung

Zusammenfassung einiger häufiger Probleme bei der Java-Programmierung

高洛峰
高洛峰Original
2017-01-16 16:17:271381Durchsuche

Dieser Artikel listet einige typische Fehler auf, die ich im Java-Code meiner Kollegen um mich herum gesehen habe. Offensichtlich kann die statische Code-Analyse (unser Team verwendet Qulice) nicht alle Probleme finden, weshalb ich sie hier aufführe.

Wenn Sie der Meinung sind, dass etwas fehlt, lassen Sie es mich bitte wissen und ich füge es gerne hinzu.

Alle unten aufgeführten Fehler hängen im Wesentlichen mit der objektorientierten Programmierung zusammen, insbesondere mit Javas OOP.

Verwenden Sie natürlich keine Präfixe oder Suffixe, um Klassen von Schnittstellen zu unterscheiden. Diese Namen sind beispielsweise falsch: IRecord, IfaceEmployee oder RecordInterface. Im Allgemeinen sollte der Schnittstellenname der Name der realen Entität sein und der Klassenname sollte die Implementierungsdetails beschreiben. Wenn die Implementierung nichts Besonderes ist, können Sie sie Default, Simple oder ähnlich nennen. Zum Beispiel:

class SimpleUser implements User {};
class DefaultRecord implements Record {};
class Suffixed implements Name {};
class Validated implements Content {};

Methodenname

Die Methode kann einen Wert oder eine Lücke zurückgeben. Wenn eine Methode einen Wert zurückgibt, sollte ihr Name beschreiben, was sie zurückgibt, zum Beispiel (verwenden Sie niemals das get-Präfix):

boolean isValid(String name);
String content();
int ageOf(File file);

Wenn sie void zurückgibt, sollte ihr Name beschreiben, dass sie etwas getan hat. Zum Beispiel:

void save(File file);
void process(Work work);
void append(File file, String line);

Es gibt nur eine Ausnahme von den gerade genannten Regeln – die Testmethode von JUnit zählt nicht. Dies wird weiter unten besprochen.

Der Name der Testmethode

Im JUnit-Testfall sollte der Methodenname eine englische Anweisung ohne Leerzeichen sein. Anhand eines Beispiels wird es klarer:

/**
 * HttpRequest can return its content in Unicode.
 * @throws Exception If test fails
 */
public void returnsItsContentInUnicode() throws Exception {
}

Der erste Satz in Ihrem JavaDoc sollte mit dem Namen der Klasse beginnen, die Sie testen möchten, gefolgt von einem „can“. Daher sollte Ihr erster Satz etwa lauten: „Jemand kann etwas tun.“

Der Methodenname ist ebenfalls derselbe, es gibt jedoch kein Thema. Wenn ich in der Mitte des Methodennamens ein Subjekt hinzufüge, erhalte ich einen vollständigen Satz, wie im obigen Beispiel: „HttpRequest gibt seinen Inhalt in Unicode zurück“.

Bitte beachten Sie, dass der Name der Testmethode nicht mit can beginnt. Nur Kommentare in JavaDoc beginnen mit can. Darüber hinaus sollten Methodennamen nicht mit einem Verb beginnen.

In der Praxis ist es am besten, die Testmethode zum Auslösen einer Ausnahme zu deklarieren.

Variablennamen

Vermeiden Sie kombinierte Variablennamen wie timeOfDay, firstItem oder httpRequest. Dies gilt für Klassenvariablen und Variablen innerhalb von Methoden. Variablennamen sollten lang genug sein, um Mehrdeutigkeiten innerhalb ihres sichtbaren Bereichs zu vermeiden, aber nach Möglichkeit nicht zu lang. Der Name sollte ein Substantiv im Singular oder Plural oder eine entsprechende Abkürzung sein. Beispiel:

List<String> names;
void sendThroughProxy(File file, Protocol proto);
private File content;
public HttpRequest request;

Wenn der Konstruktor die Eingabeparameter in einem neu initialisierten Objekt speichern möchte, kann es manchmal zu Konflikten zwischen den Namen seiner Parameter und Klassenattributen kommen. In diesem Fall schlage ich vor, die Vokale zu entfernen und Abkürzungen zu verwenden.

Beispiel:

public class Message {
  private String recipient;
  public Message(String rcpt) {
    this.recipient = rcpt;
  }
}

Oft können Sie anhand des Klassennamens erkennen, welchen Namen die Variable erhalten soll. Verwenden Sie einfach die zuverlässige Kleinschreibung wie folgt:

File file;
User user;
Branch branch;

Sie sollten dies jedoch niemals mit Basistypen wie Ganzzahl oder Zeichenfolge tun.

Wenn es mehrere Variablen unterschiedlicher Art gibt, können Sie die Verwendung von Adjektiven in Betracht ziehen. Beispiel:

String contact(String left, String right);

Konstruktor

Wenn Ausnahmen nicht berücksichtigt werden, sollte nur ein Konstruktor zum Speichern von Daten in Objektvariablen verwendet werden. Andere Konstruktoren rufen diesen Konstruktor mit anderen Parametern auf. Zum Beispiel:

public class Server {
  private String address;
  public Server(String uri) {
    this.address = uri;
  }
  public Server(URI uri) {
    this(uri.toString());
  }
}

Einmalige Variablen

Einmalige Variablen sollten unbedingt vermieden werden. Mit „einmalig“ meine ich hier eine Variable, die nur einmal verwendet wird. Zum Beispiel dieses:

String name = "data.txt";
return new File(name);

Die oben genannten Variablen werden nur einmal verwendet, daher kann dieser Code wie folgt umstrukturiert werden:

return new File("data.txt");

Manchmal, in seltenen Fällen—— Hauptsächlich Für eine bessere Formatierung können Einmalvariablen verwendet werden. Dies sollte jedoch möglichst vermieden werden.

Ausnahme

Unnötig zu erwähnen, dass Sie die Ausnahme niemals selbst schlucken, sondern so weit wie möglich darauf verzichten sollten. Private Methoden sollten immer geprüfte Ausnahmen auslösen.

Verwenden Sie keine Ausnahmen zur Prozesssteuerung. Beispielsweise ist der folgende Code falsch:

int size;
try {
  size = this.fileSize();
} catch (IOException ex) {
  size = 0;
}

Was soll ich tun, wenn die IOException „Datenträger ist voll“ anzeigt? Würden Sie immer noch davon ausgehen, dass die Dateigröße 0 beträgt, und mit der Verarbeitung fortfahren?

Einrückung

Die Hauptregel bezüglich der Einrückung lautet, dass die öffnende Klammer entweder am Ende der Zeile stehen oder in derselben Zeile geschlossen werden muss (das Umgekehrte gilt für schließende Klammern). Folgendes ist beispielsweise falsch, da die erste öffnende Klammer nicht in derselben Zeile geschlossen wird und weitere Zeichen dahinter stehen. Es gibt auch ein Problem mit der zweiten Klammer, da zwar Zeichen davor stehen, die entsprechende öffnende Klammer aber nicht in derselben Zeile steht:

final File file = new File(directory,
  "file.txt");

Der korrekte Einzug sollte so aussehen:

StringUtils.join(
  Arrays.asList(
    "first line",
    "second line",
    StringUtils.join(
      Arrays.asList("a", "b")
    )
  ),
  "separator"
);

Die zweite wichtige Regel bezüglich der Einrückung ist, dass man versuchen sollte, möglichst viele Zeichen gleichzeitig in eine Zeile zu schreiben – die Obergrenze liegt bei 80 Zeichen. Das obige Beispiel erfüllt diesen Punkt nicht, es kann auch verkleinert werden:

StringUtils.join(
  Arrays.asList(
    "first line", "second line",
    StringUtils.join(Arrays.asList("a", "b"))
  ),
  "separator"
);

Redundante Konstanten

当你希望在类的方法中共享信息的时候,应当使用类常量,这些信息应该是你这个类所特有的。不要把常量当作字符串或数值字面量的替代品来使用——这是非常糟糕的实践方式,它会对代码造成污染。常量(正如OOP中的任何对象一样)应当在真实世界中有它自己的含义。看下这些常量在真实生活中的意思是什么:

class Document {
  private static final String D_LETTER = "D"; // bad practice
  private static final String EXTENSION = ".doc"; // good practice
}

另一个常见的错误就是在单元测试中使用常量来避免测试方法中出现冗余的字符串或者数值的字面量。不要这么做!每个测试方法都应该有自己专属的输入值。

在每个新的测试方法中使用新的文本或者数值。它们是相互独立的。那么为什么它们还要共享同样的输入常量呢?

测试数据耦合

下面是测试方法中数据耦合的一个例子:

User user = new User("Jeff");
// maybe some other code here
MatcherAssert.assertThat(user.name(), Matchers.equalTo("Jeff"));

最后一行中,”Jeff”和第一行中的同一个字符串字面值发生了耦合。如果过了几个月,有人想把第三行这个值换一下,那么他还得花时间找出同一个方法中哪里也使用了这个”Jeff”。


为了避免这种情况,你最好还是引入一个变量。

更多Java编程中的一些常见问题汇总相关文章请关注PHP中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn