Home  >  Article  >  Java  >  Summary of some common problems in Java programming

Summary of some common problems in Java programming

高洛峰
高洛峰Original
2017-01-16 16:17:271342browse

This article lists some typical errors I saw in the Java code of my colleagues around me. Obviously, static code analysis (our team uses qulice) won't be able to find all problems, which is why I list them here.

If you think something is missing, please let me know and I'll be happy to add it.

All of the errors listed below are basically related to object-oriented programming, especially Java's OOP.

Of course, do not use prefixes or suffixes to distinguish classes and interfaces. For example, these names are wrong: IRecord, IfaceEmployee, or RecordInterface. Generally speaking, the interface name should be the name of the real-life entity, and the class name should describe its implementation details. If there is nothing special about the implementation, you can call it Default, Simple or something similar. For example:

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

Method name

The method can return a value or void. If a method returns a value, its name should describe what it returns, for example (never use the get prefix):

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

If it returns void, its name should describe what it did What. For example:

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

There is only one exception to the rules just mentioned - JUnit's test method does not count. This will be discussed below.

The name of the test method

In the JUnit test case, the method name should be an English statement without spaces. It will be clearer with an example:

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

The first sentence in your JavaDoc should start with the name of the class you want to test, followed by a can. Therefore, your first sentence should be something like "somebody can do something."

The method name is the same, but there is no theme. If I add a subject in the middle of the method name, I get a complete sentence, as in the example above: "HttpRequest returns its content in unicode".

Please note that the name of the test method does not start with can. Only comments in JavaDoc will start with can. In addition, method names should not start with a verb.

In practice, it is best to declare the test method to throw Exception.

Variable names

Avoid combined variable names, such as timeOfDay, firstItem, or httpRequest. This is true for class variables and variables within methods. Variable names should be long enough to avoid ambiguity within its visible scope, but not too long if possible. The name should be a noun in the singular or plural form, or an appropriate abbreviation. For example:

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

Sometimes, if the constructor wants to save the input parameters into a newly initialized object, the names of its parameters and class attributes may conflict. In this case, my suggestion is to remove the vowels and use abbreviations.

Example:

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

Many times, you can know what name the variable should be given by looking at the class name of the variable. Just use its lowercase form, which is reliable like this:

File file;
User user;
Branch branch;

However, you should never do this with basic types, such as Integer number or String string.

If there are multiple variables of different nature, you can consider using adjectives. For example:

String contact(String left, String right);

Construction method

If exceptions are not considered, there should be only one construction method used to store data in object variables. Other constructors call this constructor with different parameters. For example:

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

One-time variables

Using one-time variables should be avoided at all costs. What I mean by "one-time" here is a variable that is only used once. For example:

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

The above variables will only be used once, so this code can be restructured like this:

return new File("data.txt");

Sometimes, in rare cases - mainly for formatting Better looking - probably using one-time variables. However, this should be avoided as much as possible.

Exception

Needless to say, never swallow an exception yourself, but should pass it up as much as possible. Private methods should always throw checked exceptions.

Do not use exceptions for process control. For example, the following code is wrong:

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

What should I do if the IOException prompts "Disk is full"? Would you still think that the file size is 0 and continue processing?

Indentation

The main rule regarding indentation is that the opening bracket must either be at the end of the line or be closed on the same line (the opposite is true for closing brackets). For example, the following is incorrect because the first opening bracket is not closed on the same line and there are other characters after it. There is also a problem with the second bracket, because there are characters in front of it, but the corresponding opening bracket is not on the same line:

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

The correct indentation should be like this:

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

About indentation Now, the second important rule is to write as many characters as possible on a line at the same time - the upper limit is 80 characters. The above example does not satisfy this point, it can also be shortened:

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

Redundant constants

当你希望在类的方法中共享信息的时候,应当使用类常量,这些信息应该是你这个类所特有的。不要把常量当作字符串或数值字面量的替代品来使用——这是非常糟糕的实践方式,它会对代码造成污染。常量(正如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中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn