A Lot to Explore
Java 7 - Project Coin
Welcome to Java 7. Things around here are a little different than you may be used to! This is a really good thing – we have a lot to explore now that the dust has settled and Java 7 is on its way. We're going to warm you up with a gentle introduction to Java 7, but one that still acquaints you with its powerful features. We'll showcase Project Coin, a collection of small yet effective new features. You'll learn new syntax, such as an improved way of handling exceptions (multi-catch). You'll also learn about try-with-resources and how it helps you to avoid bugs in the code that deals with files or other resources such as JDBC. By the end of this article, you'll be writing Java in a new way and you'll be fully primed and ready for larger changes in Java 7 such as NIO.2. So, let's get going, shall we!
We're going to talk in some detail about some of the proposals in Project Coin. We'll discuss the syntax and the meaning of the new features and also some of the "whys" – that is, we'll try to explain the motivations behind the feature whenever possible without resorting to the full formal details of the proposals. All that material is available from the archives of the coin-dev mailing list so, if you're a budding language designer, you can read the full proposals and discussion there. Without further ado, let's kick off with our very first new Java 7 feature – string values in a switch statement.
Strings in Switch
Java's switch statement allows you to write an efficient multiple-branch statement without lots and lots of ugly nested ifs, like this:
In Java 6 and earlier versions, the values for the cases can only be constants of type byte, char, short, and int (or, technically, their reference-type equivalents, Byte, Character, Short, and Integer) or enum constants. With Java 7, the spec has been extended to allow for Strings to be used as well – they’re constants after all:
In all other respects, the switch statement remains the same; like many Project Coin changes, this really is a very simple change for making life in Java 7 a little easier.
Enhanced syntax for numeric literals
Several proposals offered new syntax for integers. The aspects that were ultimately chosen were:
• Numeric constants (one of the integer primitive types) expressed as binary values.
• A specific suffix to denote that an integer constant has type short or byte.
• Use of underscores in integer constants for readability.
None of these is particularly earth-shattering at first sight but all have, in their own way, been a minor annoyance to the Java programmer.
The first two are of special interest to the low-level programmer – the sort of person who works with raw network protocols, encryption, or other pursuits where they may have to indulge in a certain amount of bit twiddling. So let’s take a look at those first.
Before Java 7, if you’d wanted to manipulate a binary value, you’d either have had to engage in awkward (and error-prone) base conversion or write an expression like this:
int x = Integer.parseInt("1100110", 2);
This is a lot of typing just to ensure that x ends up with that bit pattern (which is 102 in decimal, by the way). There’s worse to come though. Despite looking fine at first glance, there are a number of problems. It:
• Is really verbose.
• Has a performance hit for that method call.
• Means you’d have to know about the two-argument form of parseInt().
• Requires you to remember the detail of how parseInt() behaves when it has two args.
• Makes life hard for the JIT compiler.
• Is representing a compile-time constant as a runtime expression (so it can’t be used as a value in a switch statement).
• Will give you a runtime exception (but no compile-time exception) if you get a typo in the binary value.
Fortunately, with the advent of Java 7, we can now write:
int x = 0b1100110;
Now, no one’s saying that this is doing anything that couldn’t be done before, but it has none of the problems we listed above. So, if you’ve got a reason to work with binary values – for example, low-level handling of bytes, where you can now have bit-patterns as binary constants in switch statements – this is one small feature that you might find helpful.
Underscores in numbers
You’ve probably noticed that the human mind is really quite radically different from a computer’s CPU. One specific example of this is in the way that our minds handle numbers. Humans aren’t in general very comfortable with long strings of numbers. That’s one reason we invented the hexadecimal system – because our minds find it easier to deal with shorter strings that contain more information rather than long strings containing little information per character.
That is, we find 1c372ba3 easier to deal with than 00011100001101110010101110100011, even though a CPU would really only ever see the second form.
One way that we humans deal with long strings of numbers is to break them up. A US phone number is usually represented like this:
Other long strings of numbers have separators too:
$100,000,000 (Large sums of money)
08-92-96 (UK banking sort codes)
Unfortunately, both , and – have too many possible meanings within the realm of handling numbers while programming, so we can’t use either of those as a separator. Instead, the Project Coin proposal borrowed an idea from Ruby and introduced the underscore, _, as a separator. Note that this is just a bit of easy-on-the-eyes compile time syntax – the compiler just strips out those underscores and stores the usual digits.
So, you can write 100_000_000 and you should hopefully not confuse that with 10_000_000 (unlike 100000000, which is easily confused with 10000000). Or, to apply this to our own examples:
long l2 = 2_147_483_648L;
int bitPattern = 0b0001_1100__0011_0111__0010_1011__1010_0011;
Notice how much easier it is to read the value assigned to l2. (Yes, it’s 2G, and it’s too big to fit into an int.) By now, you should be convinced of the benefit of these tweaks to the handling of integers, so let’s move on.
- Strings in Switch
- Improved Exception Handling