What you want to have to develop Java

Recently a user asked what they would need to know to develop a “small web application” using Java, including a database.
This is not a good question, really, but IRC user surial gave a lot of relevant information that’s worth preserving and adding to. This is not what surial said – if you’re interested in the actual content, see the channel logs – but this is a paraphrase that attempts to build on surial’s information.

What you need to develop in Java

Java

If you’re going to develop in Java, you obviously (hopefully) need Java itself. You want the JDK, not the JRE (the JDK includes the JRE.) You can use the official Oracle JDK, OpenJDK (from Red Hat, if only for more than Linux support), or Zulu – and this is not likely to be an exhaustive list by any means.
The Oracle JDK is different from OpenJDK only in some of the libraries included. Notably, the JPEG encoder is closed source, so OpenJDK’s JPEG support is not part of OpenJDK itself. Other builds may not have the same problem.
If in doubt, use Oracle’s JDK. There’s nothing wrong with OpenJDK, but when people mention the JDK, they usually mean the official JDK in terms of features and support.
One word about versions: use Java 8. Older versions have already been end-of-lifed, even though they’re still available through archives.

An Editor

Want to start a war? Make a firm recommendation for a development environment, and insult the other environments. The truth is, Java uses text as source; use what works for you.
Popular choices for development environments are IDEA (with both commercial and free versions, although people think of the commercial versions first), Eclipse (also with commercial and free versions, where people think of the free versions first), and Netbeans (with free versions and probably some commercial versions hanging out somewhere.)
All three are quite capable in their own ways. Eclipse is famous for having a perspectives-driven approach, where IDEA and Netbeans are more traditional. They all have free versions; try them out and see what works for you.
Of course, there’s nothing preventing you from using any other editor, either: Sublime Text, Atom, Brackets, vim, emacs, or anything else that can generate text.

A Build System

Strictly speaking, you don’t have to have a build tool. You could always compile manually, by typing javac, after all, and save yourself some work by maybe using a batch file.
Or, if you’re using a Java IDE like IDEA, Eclipse, or Netbeans, you could always use the IDE to build your project. In practice, your IDE will be compiling your project if only to run local tests and tell you about issues in your code, after all.
However… what you should be using is one of Maven, Gradle, SBT, or Kobalt (probably in order of desirability, and as with the other lists in this article, this is not exhaustive).
These build systems allow you to write a configuration that describes your build in such a way that the build is portable to other systems, including integration servers and, well, other users. If you rely on a batch file, you’re hoping that their filesystem and operating system match yours; if you rely on an IDE, you’re hoping that others use the same tools you do.
They don’t. Even if they do, they don’t.
A build system includes the ability to manage dependencies (the libraries your application might use) and other such things, and will also provide the ability to run tests automatically as part of your build process.
Each build system’s configuration can either be loaded by an IDE, or can export an IDE configuration, so you can use any IDE without worrying about the project.
In real terms: use Maven unless you have some process that you need fine-grained control over; if you do need fine-grained control over your build, use Gradle. If you’re using Scala, use SBT. If you’re interested in a new build tool’s development, try Kobalt. Don’t use Ant, make, or CMake, and for goodness’ sake don’t use javac directly after “Hello, World.” You’re not a barbarian.

Talking to a Database

If you’re working with a relational database (and you probably are, if you’re working with persistent data), you have a few ways to go: SQL (where you use JDBC to talk to the database in its own variant of SQL), object-relational mapping (where you use a library that manages data as if it were represented natively as Java objects), or a bridge between the two, where you sort of get objects but you are still thinking relationally.
Examples of ORM libraries: Hibernate and EclipseLink. You can use the JPA standard with either, although Hibernate has a native API that’s arguably more powerful. (EclipseLink probably does, too, but your author has no experience with EclipseLink’s native API, if it has one.) Note also that object-relational mapping is… imperfect. You’re gaining a lot by using Java’s data structures… and you’re losing some because those structures usually don’t map perfectly to a relational model.
Examples of others: jOOQ (“the easiest way to write SQL in Java,” according to their website), JDBI (“convenient SQL for Java”), and Spring Data (a flexible abstraction in front of nearly any persistence mechanism) – your mileage with each may vary, but they all seem to be pretty highly regarded.

Libraries

The Java ecosystem is one of Java’s greatest strengths. The nice thing about having a build tool is that it’s trivially easy to leverage the Java ecosystem, by simply specifying the “address” of a library, and then having the library and its dependencies included in your build by virtue of your build tool’s dependency management.
So: which libraries do you want to use?
There’s no real answer to that: “the ones you need” are probably the best candidates, and generally experience is how you learn which ones you need. Google searches for “java json parser” will give you workable answers for JSON parsing in Java, although they might not be the best answers – feel free to ask the ##java channel or its bot for suggestions on functionality.
However, here are some common libraries that many projects use without worrying about technical debt:

  • Guava (generalized utility library)
  • Lombok (annotations to reduce boilerplate with no runtime dependencies)
  • TestNG or JUnit (testing frameworks)

Quickstarts

If you need to get your project moving quickly, ##java has at least two quickstart projects ready for use, with a small amount of work.
If you want a Gradle project, see https://bitbucket.org/marshallpierce/java-quickstart.
For a Maven quickstart, see https://github.com/jottinger/starter-archetype.

First steps: Structure of your first source file

This is what a class file ought to look like when you take your first steps writing java programs:

public class YourAppNameHere {
  public static void main(String[] args) {
    new YourAppNameHere().go();
  }
  private String iAmAField;
  void go() {
    System.out.println("Your code goes here!");
  }
  void someOtherMethod() {
    // You can call this method from 'go' with: someOtherMethod()
    iAmAField = "Hello, World!";
  }
}

In particular, copy/paste the main() method verbatim and don’t touch it. If you need access to the command line arguments, pass the args parameter directly to your go method, and update the go method to take String[] args as parameter.

Editor’s note: Another way of handling arguments is to use JCommander, which itself encourages the kind of object design in this post.

Why should you do it this way? The short answer is: Because main() has to be static, but the idea of static is advanced java. You will and should learn about it in time, but trying to explain it to you (so that you don’t make mistakes because you don’t understand what that means) as you take your first steps is a bit like teaching you about the fuel gauge during your first drive. It’s just not that interesting, and you don’t need to know about it to start taking your first steps. It’ll become much more obvious once you’ve done some exercises. This main() method will get you out of static immediately so that you can ignore its existence until the time comes to learn about what it’s for.

Use exceptions correctly

In this article we are going to address the common misuse of exceptions, more specifically those times when programmers fail to correctly propagate exceptions. Along the way, and most of this article, we will talk about the differences between runtime and checked exceptions and the ways in which it is appropriate to use them.

Runtime exceptions

There are two main differences between checked, or “normal,” exceptions, and runtime exceptions:

  • Runtime exceptions don’t have to be mentioned in a method’s signature, and the compiler doesn’t warn about them.
  • The compiler doesn’t require that runtime exceptions are caught.

This means that when a runtime exception is thrown it has the potential to propagate to the JVM without any prior warning, thus crashing the application. This makes runtime exceptions bad for managing errors that are recoverable, and great for failing the application for errors that are irrecoverable such as defective code.

Checked exceptions

Checked exceptions are different from runtime exceptions in that:

  • Checked exceptions have to be mentioned in a method’s signature.
  • Checked exceptions have to be caught, or the code will not compile. (Exception handling is forced by the specification and compiler.)

This means that checked exceptions never propagate up to the JVM and cannot crash your application unless you have deliberately allowed it by including them in your main method’s signature. This makes checked exceptions great for managing errors that are recoverable, and bad for errors that are irrecoverable. Who would want to keep catching exceptions that they can do absolutely nothing about? (Answer: nobody.)

The meaning of “recovery” from errors

“Recovery” means different things to different people (and situations, and applications).
Imagine that we are trying to connect to a server and the server is not responding. It’s possible to recover from the resulting exception by connecting to a different server, given that it has the same capabilities of the server to which we originally tried to connect.
This will achieve the original goal, thus we have recovered from the error.
This is not exactly what recovery means in this context — if it’s possible to make such recovery as was mentioned in the illustration, then by all means you should do it.
However, recovery could also be displaying an alert dialog to the user that describes the incident, or perhaps sending an email to an administrator, or even simply logging the error to a log file. All of these options qualify as ‘recovery’ – taking a valid and known course of action in the event of an exception.

Using the correct exception type

With this information about the nature of exceptions and a workable definition of “recovery” in mind, the de facto standards in industry regarding exception handling make sense, and have evidently been practiced in the JVM and the Java runtime library itself:

  • If the cause of the error is because the code is incorrect, throw a runtime exception.
  • If the cause of the error is because of state while the code is correct, throw a checked exception.

The reason for this is that if the code is correct, the matter is very likely to be recoverable.
Examples include situations where you try to connect to a server without an internet connection — there is no need to crash the app. A gentle way to deal with the error is to display an error dialog that explains what happened, allowing the user to fix their connection, given a clear enough message.
If the error is in the code, and the program itself is defective, then writing a recovery path is irrelevant — how can you recover from a problem that you don’t even know exists yet? Or if you do know what the problem is, then why write a recovery path at all instead of fixing the problem?
Runtime exception examples
The following is an error for which a runtime exception is appropriate:

float nan = 1 / 0;

This will throw a division by zero exception. It is appropriate because the only means of fixing this issue is to modify the code, it is not dependent on any external state.
Here’s another example, a portion of HashMap‘s constructor:

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
    // more irrelevant code
}

In the case presented above it is also appropriate to throw runtime exceptions, because it is not logically sound to construct a hash map with negative capacity, or a load factor that is not a positive number. This error is not due to something that was transmitted over the network, the state of a file or the disk, user input, or any other external state — it’s because a calculation is wrong, or the flow is inappropriate in that it permitted these values. Either way — it’s the code that has to be fixed.
Checked exception example
The following is a rather common example of “exception handling,” often written by programmers who think that they’re following Spring‘s example:

public Data dataAccessCode(){
    try {
        // ..some code that throws SQLException
    } catch(SQLException ex) {
        throw new RuntimeException(ex);
    }
}

Honestly, the frustration of a person who would take part in such an abomination is understandable. What can they possibly do in that method to deal with an SQL exception? It’s an exception in the database, there are no means of “recovery,” and this scope is probably incapable of accessing the UI to display an error dialog. Some more sophisticated evil-doers solve this by doing something of this sort:

public Data dataAccessCode() {
    try {
        // ..some code that throws SQLException
    } catch(SQLException ex) {
        // TODO: add internationalization?
        UIManager.showErrorDialog(
          "We don't know what you're trying to do, but uhh, can't access data. Sorry.", ex);
    }
}

This does perform a certain effort at recovery, however it may not always be the correct recovery that is appropriate for the grander scheme, nor is it necessary evil. The correct way to solve this is to simply not handle the exception in this scope, and propagate the exception:

public Data dataAccessCode() throws SQLException {
    // ..some code that throws SQLException
}

This way, the code is not even “uglified” and it allows for the possibility of recovery by the caller, which is more aware of the grander scheme of things:

public void loadDataAndShowUiBecauseUserClickedThatButton() {
    try {
        Data data = dataAccessCode();
        showUiForData(data);
    } catch (SQLException e) {
        // This method’s scope can do UI, so we don't need sorcery to show an error dialog.
        // messages is an internationalized ResourceBundle.
        showErrorDialog(messages.getString("inaccessibleData"));
    }
}

Ending notes

Exceptions are a wonderful feature; it is worthwhile to use them. Don’t invent your own ways to handle and propagate errors; you’ll have less trouble and better results if you stick to the idiom instead of fighting with the platform that you are using.

Collapsing multiple ints into a long

Every now and then, you may want to collapse multiple values into a long, to use as a key for a Map, for example.
The following code is an example of collapsing three ints into one long. Obvious care should be taken here: three ints don’t actually fit into one long, so the excess bits are just discarded. If we do this, we can afford to use the lowest 20 bits, plus the sign bit, leaving us with a data range of 1,048,576 to -1,048,575.
For each int we take the lower 20 bits:

  input & 0xfffff

…and the sign bit, which we move to position 21:

  (input & Integer.MIN_VALUE) >>> 11

and then combine the two:

  (input & 0xfffff | (input & Integer.MIN_VALUE) >>> 11)

Now, we repeat the process for all our inputs and put them in our long, shifting two of them by 21 and 42 respectively so they don’t overlap:

  long l = 0;
  l |= (long)(input1 & 0xfffff | (input1 & Integer.MIN_VALUE) >>> 11);
  l |= (long)(input2 & 0xfffff | (input2 & Integer.MIN_VALUE) >>> 11) << 21;
  l |= (long)(input3 & 0xfffff | (input3 & Integer.MIN_VALUE) >>> 11) << 42;

If you were to combined a higher amount of things with less bits, this loop version will probably be more concise, courtesy of Maldivia:

  public static long pack(int i1, int i2, int i3) {
    int[] data = new int[] { i1, i2, i3 };
    long l = 0;
    for (int i = 0; i < 3; i++) {
       l |= (long)(data[i] & 0xfffff | (data[i] & Integer.MIN_VALUE) >>> 11) << (i * 21);
    }
    return l;
  }

And to unpack the long back into pieces:

  public static int[] unpack(long l) {
    int[] res = new int[3];
    for (int i = 0; i < 3; i++) {
       res[i] = (int) (l & 0xfffff);
       if ((l & 0x100000) != 0) {
         res[i] |= 0xfff00000;
       }
       l >>>= 21;
    }
    return res;
  }