java7新特性之Enhanced syntax for numeric literals
java7新特性之Enhanced syntax for numeric literals
There were several separate proposals around new syntax for the integral types. The
following aspects were eventually chosen:
■ Numeric constants (that is, one of the integer primitive types) may now be
expressed as binary literals.
■ Underscores may be used in integer constants to improve readability
Neither of these is, at first sight, particularly earth-shattering, but both have been
minor annoyances to Java programmers.
These are both of special interest to the low-level programmer—the sort of person
who works with raw network protocols, encryption, or other pursuits, where a certain
amount of bit twiddling is involved. Let’s begin with a look at binary literals.
BINARY LITERALS
Before Java 7, if you wanted to manipulate a binary value, you’d have had to either
engage in awkward (and error-prone) base conversion or utilize parseX methods. For
example, if you wanted to ensure that an int x represented the bit pattern for the decimal value 102 correctly, you’d write an expression like:
int x = Integer.parseInt("1100110", 2);
This is a lot of code just to ensure that x ends up with the correct bit pattern. There’s
worse to come though. Despite looking fine, there are a number of problems with
this approach:
■ It’s really verbose.
■ There is a performance hit for that method call.
■ You’d have to know about the two-argument form of parseInt().
■ You need to remember the details of how parseInt()behaves when it has
two arguments.
■ It makes life hard for the JIT compiler.
■ It represents a compile-time constant as a runtime expression, which means the
constant can’t be used as a value in a switch statement.
■ It will give you a RuntimeException (but no compile-time exception) if you
have a typo in the binary value.
Fortunately, with the advent of Java 7, we can now write this:
int x = 0b1100110;
No one’s saying that this is doing anything that couldn’t be done before, but it has
none of the problems we listed.
If you’ve got a reason to work with binary, you’ll be glad to have this small feature.
For example, when doing low-level handling of bytes, you can now have bit patterns as
binary constants in switch statements.
Another small, yet useful, new feature for representing groups of bits or other long
numeric representations is underscores in numbers.
UNDERSCORES IN NUMBERS
You’ve probably noticed that the human mind is 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 hexadecimal—because our minds find it easier to deal with
shorter strings that contain more information, rather than long strings containing not
much information per character.
That is, we find 1c372ba3 easier to deal with than
00011100001101110010101110100011, even though a CPU would only ever see the
second form. One way that we humans deal with long strings of numbers is to break
them up. A U.S. phone number is usually represented like this: 404-555-0122.
NOTE If you’re like the (European) authors and have ever wondered why US
phone numbers in films or books always start with 555, it’s because the numbers 555-01xx are reserved for fictional use—precisely to prevent real people
getting calls from people who take their Hollywood movies a little too seriously.
Other long strings of numbers have separators too:
■ $100,000,000 (large sums of money)
■ 08-92-96 (UK banking sort codes)
Unfortunately, both the comma (,) and hyphen (-) have too many possible meanings
within the realm of handling numbers in programming, so we can’t use either 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 compiletime syntax. The compiler strips out those underscores and stores the usual digits.
This means that you can write 100_000_000 and hopefully not confuse it with
10_000_000, whereas 100000000 is easily confused with 10000000. Let’s look at a couple of examples, at least one of which should be familiar:
long anotherLong = 2_147_483_648L;
int bitPattern = 0b0001_1100__0011_0111__0010_1011__1010_0011;
Notice how much easier it is to read the value being assigned to anotherLong.
WARNING In Java, it’s still legal to use the lowercase
l character to denote a
long. For example 1010100l. Make sure you always use an uppercase
L so that
maintainers don’t get confused between the number
1 and the letter
l:
1010100L is much clearer!
By now, you should be convinced of the benefit of these tweaks to the handling of
integers, so let’s move on to looking at Java 7’s improved exception handling.
讀書筆記:The Well-Grounded Java Developer