JavaRush /Java Blog /Random EN /Typical errors in Java code.
Level 17

Typical errors in Java code.

Published in the Random EN group
This material contains the most typical errors that I have seen in the Java code of people working with me. Static analysis (we use qulice ), for obvious reasons, cannot detect all such errors, which is why I decided to list them here. All of these errors are related to object-oriented programming in general and Java in particular.
Class Names
Your class should be an abstraction of a real life object without " validators " , " controllers " , " managers " , etc. If your class name ends with "-er" it's bad design. And of course, anti-pattern helper classes like Apache's StringUtils , FileUtils , and IOUtils are great examples of terrible design patterns. Never add suffixes or prefixes to differentiate between interfaces and classes. For example, all of these names are terrible: IRecord , IfaceEmployee , or RecordInterface . Typically, the interface name is the name of the real-life object, while the class name should explain the implementation details. If nothing specific can be said about the implementation, the names " Default ", " Simple ", or something similar will do. For example: class SimpleUser implements User {}; class DefaultRecord implements Record {}; class Suffixed implements Name {}; class Validated implements Content {};
Method Names
Methods can either return " something " or return " void ". If a method returns something, then its name should explain what will be returned. For example (don't use the " get " prefix): boolean isValid(String name); String content(); int ageOf(File file); If " void " is returned, the name should clarify what the method does. For example: void save(File file); void process(Work work); void append(File file, String line); There is only one exception to this rule - JUnit test methods . They are described below.
Test Method Names
Method names in JUnit tests must be constructed as an English sentence without spaces. This is easier to explain with an example: It is /** * HttpRequest can return its content in Unicode. * @throws Exception If test fails */ public void returnsItsContentInUnicode() throws Exception { } important to start the first sentence of your JavaDoc with the name of the class you are testing followed by “ can ”. So, the first sentence should always be like the phrase " someone can do something ." The method name will state the same thing, but without the subject of testing. If I add it to the beginning of the method name, I get a complete English sentence, like in the example above: “ HttpRequest returns its content in unicode .” Please note that the test method name does not start with “ can ”. Only JavaDoc comments begin with " can ". In addition, method names should not begin with a verb ( From the translator: apparently, the author means the imperative mood of the verb ). It is good practice to indicate that an exception is thrown when declaring a test method.
Variable Names
Avoid compound variable names such as timeOfDay , firstItem , or httpRequest . I mean both class variables and method variables. The variable name should be long enough to avoid ambiguity in its scope, but not too long if possible. The name must be a singular or plural noun. For example: Sometimes there may be collisions between constructor parameters and class fields if the constructor stores input data into the created object. In this case, I recommend creating an abbreviation by removing the vowels. Example: In most cases, the best variable name will be the name of the corresponding class. Just capitalize it and you'll be fine: However, never do the same for primitive types like or . You can also use adjectives when there are several variables with different characteristics. For example: List names; void sendThroughProxy(File file, Protocol proto); private File content; public HttpRequest request; public class Message { private String recipient; public Message(String rcpt) { this.recipient = rcpt; } } File file; User user; Branch branch; Integer number String string String contact(String left, String right);
Without exception, there should be only one constructor that stores data into object variables. All other constructors must call this one with different parameters: public class Server { private String address; public Server(String uri) { this.address = uri; } public Server(URI uri) { this(uri.toString()); } }
One-time Variables
Avoid one-time variables at all costs. By “disposable” I mean variables that are used once. Like in this example: String name = "data.txt"; return new File(name); A variable is used just once, and the code can be simplified to: return new File("data.txt"); Sometimes, in very rare cases - mostly due to better formatting - one-time variables can be used. However, try to avoid such situations.
Of course, you should never "swallow" exceptions; they should be thrown as high as possible. Exceptions from private methods must be handled externally. Never use exceptions to control flow. The code in the example is incorrect: int size; try { size = this.fileSize(); } catch (IOException ex) { size = 0; } Seriously, what if the IOException says "disk is full", will you assume the file size is zero and continue?
For indentation, the general rule is that the parenthesis must either end the line or close on the same line (the opposite rule applies for the closing parenthesis). In the example below, the code is incorrect because the first parenthesis is not closed on the same line and there are characters after it. The second bracket has the same problem because there are characters before it, and there is no opening bracket on the current line. final File file = new File(directory, "file.txt"); Correct indentation should look like this: StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join( Arrays.asList("a", "b") ) ), "separator" ); The second important rule of indentation is that you should place as much as possible on one line - within 80 characters. The above example is not valid as it can be compressed: StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join(Arrays.asList("a", "b")) ), "separator" );
Redundant Constants.
Class constants should be used when you want to share access to information between class methods, and this information is a characteristic( ! ) of your class. Don't use constants as replacements for strings or numeric literals - very bad practice, it leads to code pollution. Constants (like other OOP objects) must have meaning in the real world. What is the meaning of these constants in the real world: class Document { private static final String D_LETTER = "D"; // bad practice private static final String EXTENSION = ".doc"; // good practice } Another common mistake is to use constants in unit tests to avoid duplicating string/numeric literals in test methods. Do not do that! Each test method must operate on its own set of input values. Use new texts and numbers in each new test method. The tests are independent. So why should they share the same input constants?
Test Data Coupling.
Here is an example of hooking in a test method: User user = new User("Jeff"); // maybe some other code here MatcherAssert.assertThat(, Matchers.equalTo("Jeff")); In the last line, we concatenate " Jeff " with the same string literal specified in the first line. If, a few months later, someone wants to change the value in the third line, he/she will have to spend extra time searching where else " Jeff " is used in this method. To avoid this data snagging, you should introduce a variable.