What's New in Java 7
Java 7, codenamed Dolphin, was a major update that debuted on July 7, 2011 and became available to developers on July 28, 2011. The development cycle was divided into thirteen major milestones, with the last one completed on June 6, 2011. On average, each milestone had 8 builds, primarily consisting of feature enhancements and bug fixes.
String in switch Statement
A feature long supported in other languages finally arrived in Java 7. Using String in switch-case makes code much cleaner. Under the hood, this is implemented via String.hashCode(). Consider this code:
1 | public static int getDayOfWeek(String dayOfWeek) { |
The generated bytecode:
1 | public static int getDayOfWeek(java.lang.String); |
The implementation is straightforward: lookuptable + String.equals(Object) + tableswitch.
Type Inference for Generic Instance Creation
Before Java 7, generic classes had to include type parameters upon instantiation, or the compiler would issue an unchecked conversion warning. In Java 7 and earlier:
1 | ArrayList<String> list = new ArrayList<String>(); |
Starting from Java 7, the type parameter can be omitted:
1 | ArrayList<String> list = new ArrayList<>(); |
Java 7 gave the <> symbol a catchy name – Diamond.
Multiple Exception Handling
Java 7 introduced another syntax simplification: multi-catch. Before Java 7, each catch block could only catch one exception type. APIs like java.lang.reflect.** throw a series of exceptions. With this feature, a single catch block can handle them all:
1 | try { |
Beyond handling multiple exceptions, Java 7 also added more inclusive type checking for re-thrown exceptions. Before Java 7:
1 | static class FirstException extends Exception { } |
In Java 7, you can specify the thrown exception types as FirstException and SecondException, even though the catch block catches Exception. The compiler can determine which specific exception is being re-thrown:
1 | public void rethrowException(String exceptionName) throws FirstException, SecondException { |
Support for Dynamic Language
Java is a statically-typed language – once a program is compiled, all type information is fixed. Static typing has obvious advantages for execution speed, but before Java 7, supporting dynamic languages like JavaScript and Ruby running efficiently on the JVM was difficult. Java 7 introduced the invokedynamic instruction, which links invokedynamic call sites to methods through a bootstrap method. Consider this example:
1 | def addtwo(a, b) |
+ is the invokedynamic call site. When the compiler emits an invokedynamic instruction to call +, the runtime system knows there is an adder(Integer, Integer) method and links the invokedynamic call site to it:
1 | class IntegerOps { |
In the example above, IntegerOps is a library that ships with the dynamic language runtime.
Try with Resources
try-with-resources is an extremely practical feature, especially for I/O operations. Before Java 7, you had to close streams manually:
1 | static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException { |
In Java 7, this becomes much cleaner:
1 | static String readFirstLineFromFile(String path) throws IOException { |
The only limitation is that try does not support expressions or variables.
New I/O
The New I/O API introduced in Java 7, also known as NIO.2 or AIO (Asynchronous I/O), includes the following updates:
- File System API
- java.nio.file.*
- java.nio.file.attribute.*
- Channels API
- Socket Channel API
- Multicast
- Asynchronous I/O
- Future style API
- Callback style API
- Socket Channel API
- Miscellaneous
- Infinibind (IB) Sockets Direct Protocol (SDP)
- Stream Control Transport Protocol (SCTP)
For a deeper dive, see: Java Tutorials: Java NIO.2
Binary Literals
Binary Literals is a practical feature. Before Java 7, representing binary values required hexadecimal notation. In Java 7, you can directly use binary (prefixed with 0b or 0B):
1 | // An 8-bit 'byte' value: |
Underscore in Number Literals
This feature may seem somewhat trivial – it’s probably meant to improve the readability of long numbers:
1 | long creditCardNumber = 1234_5678_9012_3456L; |
Note that underscores can only appear between digits, not at the beginning or end of a number, nor adjacent to a decimal point:
1 | float pi1 = 3_.1415F; // Invalid; cannot put underscores adjacent to a decimal point |
Improved Compiler Warnings and Errors
Java 7 improvements to compiler warnings and errors cover the following areas:
- Heap Pollution
- Variable Arguments Methods and Non-Reifiable Formal Parameters
- Potential Vulnerabilities of Varargs Methods with Non-Reifiable Formal Parameters
- Suppressing Warnings from Varargs Methods with Non-Reifiable Formal Parameters
Fork/Join Framework
The fork/join framework introduced in Java 7 is an implementation of the ExecutorService interface that takes full advantage of multi-core processors. It is designed for tasks that can be recursively split into smaller pieces, leveraging all available processing power to improve application performance. The core of the fork/join framework is ForkJoinPool, which extends AbstractExecutorService and implements the work-stealing algorithm. Here is an example:
1 | public class ForkBlur extends RecursiveAction { |
Garbage-First Collector (G1)
The G1 garbage collector was not fully supported until Oracle JDK 7 update 4. G1 is primarily designed for garbage collection on multi-core servers with large heap memory. G1 works by dividing the heap into a series of equal-sized contiguous regions, then performing a concurrent global marking phase to determine object liveness across the entire heap. Once marking is complete, G1 knows which regions are mostly empty and collects those first, freeing up significant space – hence the name. G1 focuses its collection and compaction activity on heap regions likely to be full of reclaimable objects. It uses a pause prediction model to meet user-defined pause time targets and selects the number of regions to collect based on the specified pause time goal.
PermGen Removal
Starting from Java 7, some data previously residing in the permanent generation was moved to the Java heap or native heap:
- The symbol table was moved to native heap
- Interned Strings were moved to the Java heap
- Static members of classes were moved to the Java heap
For more details, see: https://www.oracle.com/java/technologies/javase/jdk7-relnotes.html
- Blog Link: https://johnsonlee.io/2021/05/07/java-7-new-features.en/
- Copyright Declaration: 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
