Java coding conventions, practices, and attitudes to improve readability and reliability. Please use it after paying attention to the following.
First, only the rules are presented. See below for an explanation.
boolean is confusing when used as a method argument. You can't understand without checking the method specifications. The meaning is easy to understand if you use enum. It doesn't matter if it is used locally in the method or the return value of the method.
boolean isActive = true;
The following is easier to understand than the above.
boolean ACTIVE = true; boolean IN_ACTIVE = false; boolean status = IN_ACTIVE;
You can understand the meaning even if you use it as a method argument However, passing a boolean with a different meaning does not result in a compile error. Enums are really good.
The reason is difficult to understand by reading the source. It is especially difficult to understand when the negative condition is set. It is difficult to understand when combined with other conditions.
boolean notFound = true; if (! notFound) {// ← confusing // Processing when found. }
The reason is difficult to understand with String. The name is also String, the address is String, the company name is String, and the department name is also String. Even if you make a strange assignment or make a mistake in the argument, a compile error will not occur. I really want to use class CompanyName extends String {}, but I can't. ⇒ String is final. So class CompanyName {private String value; ...}.
But in all respects, trying to do this is quite annoying. You need to redefine the methods of String (although you only need what you need). When using an external library, it is always necessary to perform conversion / inverse conversion.
I don't understand the meaning of null when assigning or passing it to a method, especially when passing it to a method.
class Address { // Processing omitted } class MyClass { public void method(Address addr) { // Processing omitted } }
// This makes it difficult to understand what null was passed MyClass myObj = new MyClass(); myObj.method (null); // ⇒ I don't know
// You should do as follows Address Address_IS_NULL = (Address)null; myObj.method (Address_IS_NULL); // ⇒ Easy to understand
Note, it seems better to define null definition in the class (Address in this example). Quote as Address.IS_NULL But when you're not in charge, do the above.
If it is int, it will not be checked even if an invalid value is assigned. However, if the existing system uses int constants, it is unavoidable to use int constants.
// Gender definition in int final int GENDER_MALE = 1; final int GENDER_FEMALE = 2; int intGender = GENDER_MALE; intGender = 100; // ⇒ No compiler error
// Actually it is better to enum than the above Gender enumGender = Gender.MALE;
// this will be false new Integer(0) == new Integer(0) // I don't know if this is a bug.
This is also the same as not using the int constant. It is not checked even if an invalid value is assigned. However, if you are using the String constant in your existing system, it is unavoidable.
final String GENDER_MALE = "male"; final String GENDER_FEMALE = "female"; String stringGender = GENDER_FEMALE; stringGender = "abc"; // ⇒ No compilation error
// Make it more enum than above Gender enumGender = Gender.FEMALE;
Supplement. On the DB, it is a numerical value or a character, and if it is an enum in the memory, it is incompatible ⇒ It is necessary to convert each other. If you implement static fromInt (fromString) in the enum and implement toInt (toString), you can create a general class that performs conversion.
It can be difficult to decide whether to use an array or a List, but it is a good idea to decide on such a principle.
If you just write a constant, you don't understand the meaning. When modifying, it is possible to modify another part of the same value.
// I don't understand this, you may change gender by mistake when changing 1 of status to another value. int status = 1; // I don't understand the meaning int gender = 1; // I don't understand the meaning
// If you do the following, it will be easier to understand and there will be no mistakes to change. final int STATUS_ACTIVE = 1; final int STATUS_INSCTIVE = 2; final int GENDER_MALE = 1; final int GEDNER_FEMALE = 2; status = STATUS_ACTIVE; // Easy to understand gender = GENDER_MALE; // Easy to understand
Note, this example should really be changed to an enum
One variable should be used for only one meaning. I know, but be aware that it's not impossible to make mistakes when you're busy.
If you assign to a variable multiple times, the value will be difficult to understand when processing with that variable. What is called "reassignment" is delicate. For example, the following would be fine. Assign values to instance variables and related variables when processing instances one after another in a loop. Set an initial value, update that value under some conditions, and then process using that variable. An example of a bad case. After assigning a value to a variable, process using that variable, then assign to a value, and process using that variable. See "Block bulk processing".
To make it easier to understand that the intent is a type parameter If the above intention can be realized, other methods may be used, but this area does not conflict with other rules.
If it is a String, str etc. This is especially good for common classes
The reason is to quickly grasp the list of fields. In the instance class, in addition to fields, routine methods such as setter / getter are defined. When looking at the source, I want to be able to instantly grasp what kind of fields there are by looking at the beginning part. Therefore, write only the field definition at the beginning, and write the comment of the field on one line without line breaks.
In the logic class, I want to know the public method. The fields used for internal processing are unnecessary from the standpoint of using the class, so they are described at the end. Public variables / constants should be written at the beginning, but private constants should be written at the end.
Those that are clearly referenced from outside the own package should be made public. Classes other than (for the time being) do not have public. If necessary, make it public at that point, but at that time there will be a timing to think "whether this should be public or not?" As a negative effect, the person in charge of another package may create a similar class without knowing that there is a class that can be used.
It's not essential, but it's common sense. Normally, constructors don't do much processing, so if you add something else, other people may misunderstand it.
Fields are not initialized on the declaration line. Do it in the initialization method. It will be easier to understand what is being initialized. Useful when reinitialization is needed. The final is to prevent overriding. Overriding the method called in the constructor makes it strange. Details omitted. Note, the name of the initialization method of the inherited class needs to be considered separately.
Naturally to prevent misunderstanding. Do not make the method name of any other purpose the same as the initialization method.
constructor When there is no processing, it is correct to specify that fact. However, there should be processing if the field initialization is made into a method. The constructor of the inherited class may not be processed It can be seen that "after considering whether or not processing is necessary, it was decided that it is not necessary."
Method Is there a method that has no processing? ⇒ It is possible when the method is overridden. Describe as "no processing" ⇒ It is important to describe in this case. It can be seen that "after considering whether or not processing is necessary, it was decided that it is not necessary."
In many cases, it is not necessary, but for the time being, the principle of "creating" is used. It can be judged individually as "not necessary in this class".
Consider passing it to another logic class as an interface Don't let the handed over class do whatever you want. You can clearly see what the handed-over class should do. You should (maybe) create an interface just for that.
The reason is as above. If it is a class, the class name is described, so it is easy to understand what constant and where it is defined.
Note, this is a fairly exceptional case. There is a static constant in the common class, and it is convenient to use a static block when initializing it. It is executed at the timing when it was first used, so there is no need to consider the execution timing. However, an exception cannot be issued in a static block (← a compile error occurs). If an exception occurs in the processing of static blocks by all means, catch it internally, output a log, and throw a RuntimeException, and the compilation will pass.
Classes that are not used elsewhere are defined locally. It's annoying and misleading when you go outside. Same as limiting variables to as narrow a scope as possible.
The reason is that the list of Comparator can be found immediately in JavaDoc. . // Do the following. interface OurComparator extends Comparator {} class OurClass implements OurComparator { .... }
The reason is as follows You can immediately see what you are implementing / inheriting by name Displayed next to it in Eclipse.
// For example: / ** Employee. * / class Staff {} /** Management. */ class StaffManager extends Staff{}
problem The name doesn't look right in English. If there are multiple implementations / inheritances, it is necessary to limit to one. If there are multiple hierarchies, the name will get longer and longer.
When you create a derived class, you may not need the methods of the base class. You can prevent the wrong call by overriding that method and raising a RuntimeException.
This is common sense, but it doesn't seem to be done. I do too. So make a rule and don't forget it.
It is useful for debugging, so I definitely want to implement it. You can create a general-purpose helper by connecting the required fields to String.
These are often unnecessary. Make a rule to implement it and judge individually that "it is not necessary to implement it in this class".
Especially when the return value is boolean. It is the same as the name of the boolean variable, which makes it difficult to understand. It may not be difficult to understand, so individual judgment is required.
In the case of empty, the processing when data is obtained and when it is not can be the same. This is a merit.
However, it is better to make an explicit judgment. Let's decide which one to use in the system. See "Create a static method in the original class to determine if the return value is normal".
It is up to the caller to decide what to do after returning the return value. It's unclear if the method will interpret it as intended.
// Do the following to improve even a little class MyClass { / ** Method to call * / public String method(String str) { // Some processing return null; // Error occurred } / ** Method to determine return value * / public static boolean errorHappened(String value) { return (value == null); } }
MyClass myObj = new MyClass(); String returnValue = myObj.method("aaaa"); if (MyClass.errorHappened(returnValue)) { // Error handling }
I know there are criticisms of "overdoing".
class MyClass { public boolean check(String str) { // Something to do return true; } public boolean checkNormalEnded(String str) { // Something to do return true; } }
MyClass myObj = new MyClass(); // I don't understand the meaning of the if statement. if (myObj.check("aaaa")) { // Some processing }
// I understand the meaning here if (myObj.checkNormalEnded("aaaa")) { // Some processing }
There is a risk of being tampered with if you return the internal List etc. So return the copy. Serpentine, ArrayList is Cloneable but List is not Cloneable
You will create a class for the return value. But if the class doesn't seem to be available elsewhere, it's very disappointing. But usually, put up with regret and do this.
// If you say "I really don't like it" in the previous section, do the following class Box { public Object[] getSize() { // First is height, next is width return new Integer[]{5,10}; } public static Integer getHeight(Object[] values) { return (Integer)values[0]; } public static Integer getWidth(Object[] values) { return (Integer)values[1]; } }
Box box = new Box(); Object[] values = box.getSize(); int width = Box.getWidth(values); int height = Box.getHeight(values);
There is no need to new, the meaning is easy to understand because the class name is written I think it's common sense to do this, but sometimes I see something that is an intern method.
You can tell by checking the arguments, but it's a hassle. Should be distinguishable by method name
Now a natural recognition If you need speed, do so.
Think of the following Is there a simpler logic? Isn't the idea wrong? Is it the necessary logic in the first place? If you still need it, do it!
In order to realize one process, multiple lines may be written. For example, put values in some variables and call a method. At such times, block these series of lines to lower the indent. By making it a block, you can see that these lines are a series of cohesive processes. You can add comments to the entire block Since variables can be defined inside the block, accidental explosion of variables can be prevented.
// This is a comment for the entire block, describing a series of processing in the block { int a = 0; String str = "abc"; // Continue below. }
// Many people write if ~ else as follows int a = 1; if (a == 1) { // Required processing } else { // Another process }
Describe it as follows The reason is that you can comment on the entire else See "Make a set of processes a block" above.
if (a == 1) { // Required processing } // Processing in case of else ⇒ Here is the comment of the whole else else { // Another process }
This is natural, but I often see programs that I'm not using. Large number of lines, verbose, hard to see, annoying. However, the nested ternary operator is not used.
// Addition, use the ternary operator even when there is no else → The number of lines is reduced a = (logical formula)? A = algebraic expression: a;
// do the following if (logical expression) {break;}
The reason is to reduce the number of lines and display as many as possible on the screen. In other cases, it is prohibited because the logic flows down and it becomes difficult to see.
Occasionally I see a program that is judged by ==. If you look closely, you may become anemic. Moreover, it passes the test. The reason for passing the test is that if you copy it, it will be the same.
This is to prevent it from falling null. However, if you need a proper null check, you need to check it in the previous line.
String str = "bbbb"; if ("aaaa".equals ((str))) {// Note, "aaaa" should be defined as a constant // Processing when there is a match }
Boolean can only be true, false (and null) and it is defined in the Boolean class so there is no need to new Note, (new Boolean (true)) == (new Boolean (true)) is false.
Boolean boolValue = Boolean.TRUE;
Aside from assigning to a variable, mistakes are likely to occur when passed to an argument. I get anxious and see the method of the other party to confirm.
class MyClass { public void method(String str) { // Something to do } }
// do the following MyClass myObj = new MyClass(); myObj.method((String)null);
The truth is, it's better to redefine null. See "Redefine and use null ⇒ class name + IS_NULL".
The reason is that it bugs when I try to add a sentence.
Even if you use it, the result is the same, but you can not see that "processing in order" in the source code.
// Example of using an if statement int a = 1; String msg; if (a == 0) { msg = "aaaa"; } else if (a == 1) { msg = "bbbb"; } // Continue below.
// do the following String[] msgs = new String[] {"aaaa","bbbb"}; msg = msgs[a];
This example isn't appreciated, but when building a state machine or something, it's confusing if you don't do this. Note, if the original value is not zero origin, you need to make the array two-tiered Since it is only a constant table, it will be shorter and easier to see ⇒ less bugs
int a = 0; if (a == 0) { // Describe some processing } else { // No processing }
Of course, not all if statements do this. Only if there is room for doubt. It is possible to convey that "it was decided that it was unnecessary after considering whether or not else processing was necessary".
It may be difficult to understand because many conditions are connected by and in the if statement. In such a case, decompose the condition and nest the if statement. Don't be afraid to be criticized as "amateur". Emphasis should be placed on making it easy to understand without bugs.
When several conditions are connected by and / or, it is easier to see if each is enclosed in () and separated.
Since the cost of creating an object is wasteful, it may cause a bug if it is reused. Don't worry, it's better to create a new object. Of course, if necessary for performance, use it again.
It becomes clear that you are calling a static method, making the source easier to read.
This will be criticized, but the visibility of the source is more important. Certainly the performance is different, but in many cases the absolute time is short in the first place. Don't use StringBuilder unless you have a lot of loops. Note, in my measurement, it takes about 10 times when StringBuilder (StringBuffer) is not used in the additional processing of String.
This is also a situational judgment, but it is better to go out to some extent. However, if you overdo it, the number of methods will increase and you will be confused.
You may forget the process to add after new, so make it a habit and don't forget This is a confusing bug (sometimes) so to prevent it
The above exception is when the value is set for the new object and it may not be added depending on the conditions.
It may or may not be caught, but most will not. Finally is attached so as not to forget Even when finally processing is unnecessary, add an empty finally and write "no processing"
I see that the date and time processing is similar in various parts of the system. The same format is described in various places. Also, especially when performing date processing, bugs may enter due to time errors, so it is necessary to prevent it.
It is the same as going out as DAO for DB access, and a little special processing like these is made a common class.
In primitive, you need to create a method for each type. You can unify with Number in wrapper. However, Big Decimal is also Number, which is troublesome.
In the common class, the class name and method name may not match the business content. In such a case, define a derived class and give it a descriptive name. If you just overdo it, the number of classes will increase.
Establishing a common class within the project is rather a cost-increasing factor ⇒ However, it should be established. The cost of maintenance and the cost of members grasping the specifications are higher. The maintenance of common classes within the project is to improve quality. If you do not recognize this, you will be frustrated.
In the long run, it will also lead to cost reduction.
Recommended Posts