Home Curly brackets and indentation
Always include curly brackets
Always include curly brackets, even for one-line if statements or for loops.
Java has a "feature" which allows you to omit curly brackets when writing if statements, for loops, or while loops containing only a single statement. You should never use this feature – always include curly brackets.
More specifically, Java will let you do something like this:
if (something) System.out.println("Look, no curly brackets!");
However, you should ALWAYS include curly brackets and do the following instead:
if (something) { System.out.println("Curly brackets!"); }
The reason for this is because omitting curly brackets increases your chances of writing buggy code. For example, take the following code:
if (getStatus(message) == MESSAGE_VALID_STATUS) turnOnLights();
What this snippet of code is doing is fairly obvious – if the status of the message is valid, it'll turn on lights (perhaps we're coding a robot, who knows).
Now, let's say that several months down the line, either you or your teammate needs to revisit this segment of code so that our robot both turns on the lights and starts driving forward. So then, you modify your code to look like this:
if (getStatus(message) == MESSAGE_VALID_STATUS) turnOnLights(); driveForward();
Is this correct? No!
It may not be obvious because of the indentation, but because we omitted curly brackets, the above snippet of code is actually equal to:
if (getStatus(message) = MESSAGE_VALID_STATUS) { turnOnLights(); } driveForward();
If you don't include curly braces, you will always have to vigilant to make sure you don't accidentally write a similar bug. If you always include braces, you can forget this category of bug exists altogether.
And while this may seem like a silly and basic mistake, this exact same bug actually occurred to Apple in 2014. In their SSL verification code, which is responsible for making sure things like your passwords and banking information stays secure, Apple had the following lines of code:
hashOut.data = hashes + SSL_MD5_DIGEST_LEN; hashOut.length = SSL_SHA1_DIGEST_LEN; if ((err = SSLFreeBuffer(&hashCtx)) != 0) goto fail; if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; /* BUG! Code will always goto the failure case */ if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; err = sslRawVerify(...);
This is in C, so the details are a little different then Java, but essentially it's the same bug. Somebody accidentally copied a line of code on line 13, which falls outside of the if statement and causes the code to skip a few checks and jump immediately to the error handling section of the code, which then returns a success message.
So, that means that under certain conditions, attackers could exploit this to circumvent Apple's security system by skipping those additional checks, completely breaking security. More specifically, it allowed an attacker to capture or modify data protected by SSL/TLS, which includes data like your banking account, social security info, credit card information, etc.
This was a hugely catastrophic bug, caused Apple huge amount of embarrassment, and could have easily been avoided if their engineers had just always used curly braces.
For a more detailed writeup about this bug, see What you need to know about Apple's SSL bug.
Indentation and nesting
When you see a matching set of opening and closing curly brackets, indent all lines of code in between by one additional level. Be consistent in how big each indent is.
Indentation is a useful tool for helping a reader visually see the "structure" of your code. Without indentation, it's easy to lose track of how your curly brackets are nested. This makes it harder to see the overall "flow" of your code.
Like many of our other rules, the compiler will not care about indentation. However, human readers do, and typically care very strongly.
Here are the guidelines you should follow:
-
Indent each line of code between two matching curly brackets by one extra level.
-
Be consistent in how much you indent each time.
If you decide to indent each new level by four spaces, you shouldn't suddenly switch to indenting by three spaces half-way through your code.
Do note that we don't care if you prefer tabs or spaces (though we do strongly suggest using spaces), or how many spaces you use per indent, as long as you're consistent.
-
Place each opening curly bracket on the same line as the preceding control flow statement, and place each closing curly bracket on a separate line.
The only possible exception to this rule is with
else
andelse if (...)
statements. Some programmers will prefer to place theelse
statement on the same line as the previous closing curly bracket for brevity. If you prefer this style, feel free to use it.
A good rule of thumb to tell if your indentation is ok is to imagine that all of your curly braces suddenly turned invisible. Can we still determine how your code is structured? If so, then your code is most likely correctly indented (or close to being so).
If you prefer another convention for indenting your code, please check with the current instructor for this quarter or ask on the message board to see if he or she is ok with that convention.
Now, let's look at an example of bad indentation. Try and see how many errors you can find:
public class MyProgram { public static void main(String[] args) { System.out.println("main-1"); System.out.println("main-2"); myMethod(); } public static void myMethod() { System.out.println("myMethod-1"); for (int i = 0; i < 10; i++) { System.out.println("myMethod-for-1"); System.out.println("myMethod-for-2"); } System.out.println("myMethod-2"); }}
This is an example of bad indentation. If we try applying the "invisible curly brackets" test to it, we can immediately see that it's very difficult to deduce the overall structure of this program from just the indentation alone:
public class MyProgram public static void main(String[] args) System.out.println("main-1"); System.out.println("main-2"); myMethod(); public static void myMethod() System.out.println("myMethod-1"); for (int i = 0; i < 10; i++) System.out.println("myMethod-for-1"); System.out.println("myMethod-for-2"); System.out.println("myMethod-2");
Here is a somewhat better, but still bad version of the above:
public class MyProgram { public static void main(String[] args) { System.out.println("main-1"); System.out.println("main-2"); myMethod(); } public static void myMethod() { System.out.println("myMethod-1"); for (int i = 0; i < 10; i++) { System.out.println("myMethod-for-1"); System.out.println("myMethod-for-2"); } System.out.println("myMethod-2"); } }
While this is better, the indentation is still not ideal. Things are not lining up perfectly, and we sometimes indent by 3 spaces, or by 5.
Here is a corrected version of the above program:
public class MyProgram { public static void main(String[] args) { System.out.println("main-1"); System.out.println("main-2"); myMethod(); } public static void myMethod() { System.out.println("myMethod-1"); for (int i = 0; i < 10; i++) { System.out.println("myMethod-for-1"); System.out.println("myMethod-for-2"); } System.out.println("myMethod-2"); } }
This is a good example of indentation. If you look at each matching set of curly brackets, each line inside is indented by four spaces, helping make the structure and flow of the code more obvious.
Even if you have no idea what a for
loop is, you can still deduce that
lines 11 and 12 "belong" or are nested inside line 10.
Here is another example of good code:
public class Grade { private double gpa; public Point(double gpa) { this.gpa = gpa; } public String getLetterGrade() { if (this.gpa > 3.5) { return "A"; } else if (this.gpa > 2.5) { return "B"; } else if (this.gpa > 1.8) { return "C"; } else if (this.gpa > 0.7) { return "D"; } else { return "F"; } } }
Unlike the previous example, we've indented 3 spaces per indent in this example. This is ok, as long as we're consistent. Each else if and else statement is also placed on the same line as the preceding curly bracket for brevity.
(And again, even if you don't recognize any of the code you see here, it's still easy to determine how the code is nested)
Here is another version of the previous code snippet that uses the alternate
else
block formatting style. This would also be acceptable.
public class Grade { private double gpa; public Point(double gpa) { this.gpa = gpa; } public String getLetterGrade() { if (this.gpa > 3.5) { return "A"; } else if (this.gpa > 2.5) { return "B"; } else if (this.gpa > 1.8) { return "C"; } else if (this.gpa > 0.7) { return "D"; } else { return "F"; } } }
Curly brackets and indent style
There are many different conventions on how exactly you should place your curly brackets. We strongly suggest you stick to standard Java conventions, but you are free to pick whatever convention you want as long as it isn't too bizarre, and more importantly, you follow it consistently.
Expand for details on our recommended style.
We strongly recommend you format your curly brackets following Java conventions:
- Do not put a new line before an opening curly bracket.
- Always start a new line after an opening curly bracket.
- A closing curly bracket should always belong on a separate line, except
for
else
statements. - Put one blank line between each method.
Here is an example of some code that follows all these conventions:
public class MyProgram { public static void main(String[] args) { System.out.println("foo"); methodA(); methodB(3); } public static void methodA() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { System.out.print("*"); } System.out.println(); } } public static void methodB(int param) { if (param > 0) { System.out.println("Positive"); } else if (param < 0) { System.out.println("Negative"); } else { System.out.println("Zero"); } } }
Do note that we allow you to deviate from these rules to some degree, as long as the
convention you pick is consistent and not too bizarre. For example, if you prefer
compressing your if/else
blocks more tightly, it would be fine to rewrite
methodB
like so:
public static void methodB(int param) { if (param > 0) { System.out.println("Positive"); } else if (param < 0) { System.out.println("Negative"); } else { System.out.println("Zero"); } }
Here is an example of some code which deviates from these rules even further, but would still be acceptable:
public class MyProgram { public static void main(String[] args) { System.out.println("foo"); methodA(); methodB(3); } public static void methodA() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { System.out.print("*"); } System.out.println(); } } public static void methodB(int param) { if (param > 0) { System.out.println("Positive"); } else if (param < 0) { System.out.println("Negative"); } else { System.out.println("Zero"); } } }
While we don't recommend you follow this style (it require more scrolling to read), you are free to do so as long as you consistently follow it.
You should never mix together multiple different styles. Doing so is sloppy and unprofessional:
public class MyProgram { public static void main(String[] args) { System.out.println("foo"); methodA(); methodB(3); } public static void methodA() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { System.out.print("*"); } System.out.println(); } } public static void methodB(int param) { if (param > 0) { System.out.println("Positive"); } else if (param < 0) { System.out.println("Negative"); } else { System.out.println("Zero"); } } }