http://www.developer.com/

Back to article

Good Java Style, Revisited


April 16, 2008

Introduction

I was recently asked to review and update an older article entitled "Good Java Style" which was presented in two parts (Part One and Part Two) by Thornton Rose; it originally ran on this site in 2001. Inasmuch as the landscape of software and the IT industry changes almost daily, I agreed to attempt an updated presentation and maybe add a bit more of the "why" based on my own experiences. Of course, as with any online article, this will not be an exhaustive survey of all Java style considerations, but I do aim to hit all the high points.

Why Style Matters

If you are writing code for a living, you are most likely working with a team of fellow developers, all battling the impossibility of feature requirements on one hand against some looming deadline on the other. The one thing that makes good teams—and breaks bad ones—is communication. Requirements, schedules, test cases, assumptions, algorithms, patterns, those little "fix me" comments: These are the thousands of little details that development staff must juggle to get something that works, as planned, out the door so that money comes back in. Although parts of that list are handled at different levels of the organization, you still must be able to effectively communicate with your fellow development staff.

Many of you probably had a high school writing teacher or college professor who required a certain style for you to follow in their class for term papers, book reports, and such. Colleges and trade organizations also have their own styles for written material (theses, journal articles, and so forth) that must be followed. Even though the logical organization of material might seem arbitrary when a single article is considered, a collection of related works, each with their own arbitrarily applied style, turns into an unusable mess. It is no different with software source code. To clearly and effectively express your thought of "this is what this code does" to other people, it is immensely helpful for everyone to have a consistent set of expectations as to how that source code is presented. Spotting the mistake in a piece of logic that fails just one time out of a hundred can sometimes be impossible to focus on when your mind is instead cluttered with little mental bookmarks about the exact context in which one little source token exists (much less its enclosing method, class, package, and so on). As a case in point: whatallismisspelledinthisentencethathsnospacesinit?

Requoting from the Java Code Conventions:

  • 80% of the lifetime cost of a software product goes to maintenance.
  • Hardly any software is maintained for its whole life by the original author(s).
  • Using good style improves the maintainability of software code.

History Note

As an aside, the preceding reference was last updated in 1999, back when we were just starting to use Java 1.2. As for the initial version of this article written in 2001, Sun had just made Java 1.3 available. We are now, in 2008, using Java 1.6, and there have been a lot of enhancements made to the language, as well as Java's role in the software ecosystem, since. Java 1.7 is even on the drawing board. However, the foregoing statements are still as true now as they ever were.

House Styles and Holy Wars

As has been mentioned above, what is truly king is that you effectively communicate with your colleagues. (In fact, just being able to communicate with yourself after a six-month break can be a good thing, too.) Seasoned software developers tend to be passionate about their preferences and their prejudices, nearly to the point of riding into glorious combat to defend the honor of their bracing style or their choice of text editor. It makes great fodder to tease each other around the lunch table, but in a team environment, communication plays a much more important role than whether the "{" is on the "right line" or not. At this point, your team of developers just needs to agree on a common style to use. (This is all the more true if you are all doing the right thing by peer reviewing each other's code.) So, if it is the case that you are the junior developer at a code shop with an established style, the professional thing to do is use that style. But, if you are shopping around for a good style to agree upon, doing a little reading about why different people and different shops use a particular style can be informative.

With that being said, I am not going to try to sell one particular approach over another unless I've seen evidence warranting me to. Moreover, some of the items that developers previously had to worry over are now being handled automatically by solid IDEs, whose general behaviors for styling, indenting, and formatting have basically attained parity with each other. Also, it may happen that an attempt to force a line or two of code into a particular style actually detracts from the general purpose of communication. I feel that clarity of purpose must win over "styling rules at all costs" approaches, so it is hard to say that any absolute ever truly exists.

The IDE Effect

Integrated Developer Environments (IDEs) for Java have matured a great deal in the past seven years. The leading contenders in the "download for free" corner are Sun's Netbeans IDE and the Eclipse IDE. Both editors offer an excellent "Format" tool that fixes basic style and presentation of source code in addition to intelligent indent handling, parenthesis matching, and code completion. Moreover, good IDEs can even have their exact formatting style tweaked to varying degrees. This means that a lot of the heavy lifting can be done for you as you write the code, and also as a one-button cleanup when you're basically finished. The use of an established Formatter configuration can also be an aid to a development group that wants to standardize on a particular code style in a simple way. (Gone are the days of manually adjusting the whitespace around code tokens to get them to adhere to a common style.) Given the sheer power of options that IDEs now provide you, it is silly in the extreme to continue to eschew them in favor of a more primitive "raw mode" text editor. Still, some people are stuck in their ways.

The Monitor Effect

In addition to solid IDE tools, the desktop monitor has likewise made great strides in physical size (and resolution), allowing more material to be shown on the screen at a time. A common code style consideration involved limiting lines of code to 80 characters, for fear that someone might need to view the material on an 80x25 text console. In all honesty, it is the 21st century now, and in the current age of large, widescreen monitors and mice that scroll horizontally as well as vertically (and the afore-mentioned IDE tools) this 80-character line length limit is becoming an anachronism. Unless you have a distinct need to keep lines short due to some process requirement or tooling limitation (or managerial mandate), I'd cast a bit of a wary eye on this one. Still, IDEs carry an option for where to draw a visual hint, with a default value of "80," and the auto-formatters tend to wrap lines that exceed this length. In this circumstance, fighting the formatter probably isn't worth a great deal of effort, but wearing out your Return and Tab keys just to wrap lines on your own isn't either. So, if an 80-character line just feels overly cramped, and your team can agree on some other limit, see what everyone thinks of 120.

General Guidelines

Tabs vs. Spaces

Whether a Tab character results in a literal '\t' being present in the code file or whether some certain number of space characters is used instead can be a issue that causes a little debate. Most people that have a reason ready say that Tabs should be expanded to space characters. Their justification for this is that a plain text file does not have the notion of "tab stops" stored in it (whereas a word processor document does), so it is hard to know whether an actual '\t' character shifts the line over as many places in two separate tools for two separate people or not. However, if the tabs are expanded to space characters, the same amount of indent is applied for everyone. The choice to do either action is usually a configurable option in any decent code editor. Another point then is how many spaces should represent a Tab. The biggest consensus is to use four (4) spaces each. (People who insist on using literal tab characters while reading in an 80x25 console are a particularly vexing breed.)

Braces

In any given if, while, do, or for loop, you will have braces surrounding that constructs instructions. The exact positioning of where the opening and closing braces goes is another great point to argue about. The main styles are:

... K&R Style ...
if (condition) {
    statement;
    statement;
}

... Allman Style ...
if (condition)
{
    statement;
    statement;
}

...Whitesmiths Style ...
if (condition)
    {
    statement;
    statement;
    }

...GNU Style ...
if (condition)
  {
    statement;
    statement;
  }

This wikipedia page has a longer discussion of these and other brace styles, and includes a few comments about their origins and motivations. My own experience is that the first two styles are the most common. The examples and tutorials that you might find on Sun's own site uses the K&R style almost exclusively, and it is hard to argue with their influence on a language they steer. As I cut my teeth on C code originally and learned Java from Sun's tutorial pages, my fingers do a K&R-style opening-brace-and-return automatically. Naturally, my current workplace uses the Allman style. Fortunately, when they want to beat me up about it, we have an Eclipse formatter configuration that makes the adjustments.

As an aside, because Java allows block statements that are not attached to a control structure, the Allman style does permit simple removal of the condition (by commenting out its line) without the need to readjust the opening brace to accommodate.

... this is syntactically okay, if logically suspicious ...
//if (condition)
{
   statement;
   statement;
}

Statements

Do not put more than one statement on a line. Syntactically this is legal, of course, but is visually distracting and messy, and invites someone later to possibly make a mistake when they edit, copy, or paste in the vicinity of such a line. Statements should occur each on their own line and should be indented property relative to their enclosing brace. (See the sections on Braces and on Continuation Lines for related points.)

Continuation Lines

If you are writing an excessively long line and you want to wrap it, the continuation line should be indented. If your long line will begin a new block that will need a brace and indented lines coming after it, the continuation line should be double-indented to further set it apart from the block statements. (And in this latter case, using the Allman bracing style does help emphasize the difference between the continuation lines and the block's statements.)

if (some really long condition that you need
   to continue here)
{
   statement;
   statement;
}

Wrapping a line to perform a continuation in the middle of a variable declaration with its initialization should be done to keep the variable declaration on one line and the initialization on the other (whenever possible). This might arise due to using a fully qualified class name, notably when you are already indented a few levels already.

...
com.acme.foo.project.data.YourObjectFactory objFactory =
   new com.acme.foo.project.data.YourObjectFactory();
...

Conditional Expressions

Simple conditional expressions are easy enough to express and be comprehended later. Things tend to get a little tricky to follow when multiple sets of grouping parentheses are used in conjunction with booleans "&&" or "||". Although a very lengthy conditional expression should indeed be wrapped into the next line, a better approach is often to declare one or more temporary boolean values such that the complexity of the conditional expression can be divided into more easily digestible chunks.

... instead of this ...
if (value != null && value.length() > 0 && (errCount = 0 ||
   isIgnorable(currentError)))
{
   ... statements ...
}

... try this ...
boolean valueIsGood = (value != null && value.length() > 0);
boolean noErrors = (errCount = 0 || isIgnorable(currentError));
if (valueIsGood && noErrors)
{
   ... statements ...
}

Omitted Braces

From a syntax perspective, it is allowable to omit the braces when only a single statement will be executed in the control structure. My experience is that this is highly dangerous: in a fast-paced, deadline-driven coding marathon, your brain might assume braces are present when in fact all that is present is a single, indented statement; and in this case, you will add what you think is a second statement to the control structure that will actually be applied in all cases. So I highly recommend, as do others, that your control statements always brace, even for a single statement. (When you do add a second statement later, your braces are already in place.)

... don't do this ...
if (condition)
   statement;

... or you might risk this bug later ...
if (condition)
   statement;
   statement;

Other Considerations

A good code editor tool will visually hint to the matching parenthesis or brace when the cursor is to one side of it. Also, you may be able to double-click on (or to one side of) a brace to have the entire inner contents selected or highlighted in some way. This does a lot to help keep track of which braces match in long, highly-nested methods (although good code style says methods shouldn't get that hairy in the first place). However, you may see code that adopts the style of commenting the closing brace to inform you of its matching condition type. (When a condition block is so long that the opening and closing brace are no longer on the same screen, this isn't an entirely bad idea... although a block of that length is.)

for (condition)
{
   ... statements
   ... lots of statements
   ... pages worth of statements
} // end for

Comments

Comments in Java come in the inline style and the block style. (And when you're writing javadoc material, you have to use a slight variant of the block style.) Although I am personally as apt to use an inline comment, notably to describe a variable's purpose in life, there is one minor drawback to them that is worth mentioning: forum posts. A lot of forums allow someone to post in source code with the understanding the petitioner will attempt some level of diligence to make sure things are legible. Invariably, new people get it wrong, or the site behaves differently than they expect. Suddenly the line breaks disappear, and all those inline comments turn the post into a useless mess because there is no way left to know where they end. So the lesson here is that, if you post a question to a forum, be careful about inline comment markers, and double-check (preview and re-edit) before committing the question to the forum.

As to comment style in general, applying a javadoc comment to the class and to all publicly visible methods (if not all methods all the time) is preferred. You will usually be forgiven if your description has some misspellings in it. You might even be forgiven if the javadoc is a little bit out of date. But you will be cursed to your death to omit a javadoc entirely, when someone else has to follow along and maintain some non-obvious method or class. (Remember: No two people have the exact same definitions for "obvious.") On the other hand, be brief with what you do provide in the comments. Reiterating the name of the method just to use regular English words and capitalization is pointless, so try to add a sentence or two beyond what you think the method or class name implies.

Also, note that Sun has a complete writeup on their recommendations for what you put into a Javadoc comment and how it should be verbally formatted.

Declaration Mechanics

Variable Declaration Locations

Class-level variables, be they static or instance, should be placed toward the top of the source code file. This is largely a matter of convention for Java, and it inherits from its roots in C-style languages that effectively require variables to be declared in this fashion. Although Java is happy to allow you to intersperse your getters, setters, and instance variables throughout the class code, other experienced developers will have a natural (and in honesty, an unconscious) expectation that all such variables are declared at the top of the file.

On the other hand, the convention for method-level variables is that they are declared and initialized as they are needed. (This is a stronger break from early C-style languages that required all function-level variables to be declared at the beginning of the function before any actual statements were present.) The justification for this difference between class-level and method-level variables is that you really should not have that many class-level variables in the first place, and that they tend to be used throughout many methods in the class; however, the method-level variables tend to have more direct and limited roles, making on-the-fly declarations less taxing to a fellow code-reader.

Naming and Capitalization

The exact appearance of a class and variable names is again a matter that largely follows an established convention. Types (classes, interfaces, and so forth) should be in lowercase letters, with no spaces between words, but with the first letter of each word (including the first word) using an uppercase letter: SomethingLikeThis. (This form is often referred to as "camel case" for, perhaps, obvious reasons.)

Non-constant variables should likewise be in lowercase letters, with no spaces between words, but with words after the first word starting with an uppercase letter: somethingLikeThis. (The key difference is that classes start with a capital letter; variables do not. Otherwise, the appearance is very similar.)

A "constant" (which in Java is a variable with the 'final' keyword, and which is usually also 'static') is named in fully uppercase letters, with word separated by underscore characters: SOMETHING_LIKE_THIS. Experienced fellow coders will again have a natural and unconscious assumption that a token which looks like that in source code represents a final variable.

class MyNeatClass
{
   private int currentValue;
   public static final String SOME_STRING_CONSTANT = "Blah blah";
   ...
   public void doSomething()
   {
      ...other statements...
      ...
      int count=0;
      for (loop condition)
      {
         if (branch condition)
         {
            count++;
         }
      }
      ...
   }
}

The recent appearance of the Java "enum" type adds a relatively new twist into the works. An enum behaves like both a class and a listing of named value constants. The capitalization of the enum itself follows that for classes and interfaces (they are, after all, "types"). The precise convention for the named value constants inside the enum is a little less clear. Even though the constant-variable appearance is natural on the one hand (and is the form used in the enums that are present in the Java API documentation) an alternate tends to use class-style capitalization instead. I believe the reason for this lies in the nature of their "toString" output: they display a String-type value that exactly matches their source-code representation, and the class-style capitalization is more user-friendly than the final-variable-style capitalization. Of course, the class-like nature of the enum means this default behavior can be overridden as needed, so the "constant variable" form should probably be used.

enum MyFirstEnum
{
   ALPHA,
   BETA,
   GAMMA,
   DELTA;
}

If the enum type is still new to you (it was introduced in 1.5) you should read this page that discusses why enums are useful and how to take advantage of their OO-like capabilities.

Source File Layout Mechanics

The exact ordering of the sections of material that compose a Java source code file follows a fairly standard convention. (The compiler also makes a couple of mandates of its own.) The accepted ordering of material is generally as follows:

  • Your team's or company's comment header, if any
  • The package declaration statement
  • Import statements
  • The declaration for the type, an "extends" clause (if any), and an "implements" clause (if any)
  • Class-level variables (as appropriate)
  • Class methods
  • Inner class declarations, if any, using this same pattern

The team or company comment header tends to be some standardized copyright statement. This is a standard comment and can of course be omitted. The package statement can be omitted, but doing so can cause unexpected headaches. (Certain frameworks and toolsets may in fact require that the code it interacts with is in a package, but such a requirement is not directly imposed by the Java compiler itself. Still, an explicit package is highly encouraged, even if it is something as simple as "dummy", "test", or just your initials.) If you do provide a package statement, it must occur as the first non-comment statement in the file, preceding any import statement.

Import statements should generally be grouped in some fashion, and the "*" import forms are discouraged for anything bigger than a quick prototype. (Using "*" import forms begs to introduce a namespace clash, or worse, to accidentally have the compiler resolve an unqualified class name against the wrong fully-resolved class.) Grouping might be that you list all the core Java API classes together (and if possible, in alphabetical order), other third-party classes together in another group, and your own application's classes together in yet another group. (Adding blank lines between these groups is also encouraged. IDEs tend to do this if you allow them to format your source code.)

Types (classes, interfaces, and so on) and methods should include a Javadoc-style comment wherever possible. (Note that the general behavior of the javadoc utility itself is that non-Javadoc'ed entities are still listed in the generated output with empty descriptions and explanations.) Public-facing types usually benefit from someone taking the effort to describe a few usage examples in the top-level Javadoc comment for the type itself; certain the listing of assumptions, corner cases, and the like should be captured in some form.

The antecedent of this document went so far as to recommend a strict ordering for each type of class-level variable. I have not personally seen this level of detail demonstrated or heard many arguments made to bolster the case, so I am personally of the opinion that related class-level variables should be basically grouped together (for example, all the private variables that back the public getter and setter methods in one group, constants in another group, and so forth) but that the overridding principle is that these variables are easy to find, clearly labelled, and commented as necessary.

The antecedent also expressed that the "main" method should be listed last, but gave no clear rationale for this. My personal opinion is that a main method is either short enough to include right off the top, or sufficiently long enough that it should exist almost entirely in a separate class in a separate file. (Historically, early C-style languages had requirements that effectively caused the implementation of the main method to be last in the file, but Java suffers no such effects.)

Conclusion

Knowing the various rules and conventions that compose a "good Java style" goes a long way to reducing the mental noise that you and your fellow team members need to battle through to get the job done. Paraphrasing a joke I once heard, one should code as though they know the person that will follow along behind them knows where they live and is also an axe-wielding maniac. (And based on people I have worked with, this sometimes seems closer to the truth than you might think.) Writing better code can start with writing code that is styled and presented better. This will in turn lead code that analyzed and debugged more easily, and this in turn will lead to code that runs better.

About the Author

Rob Lybarger is a software guy (and a degreed aerospace engineer) in the Houston, TX area who has been using Java for nearly ten years. He has used various versions of Windows, various distributions of Linux, but loves Mac OS X. He likes exploring new techniques and new approaches to organizing and wiring applications, and loves to let the computer do as much work for him as possible.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date