
Hey, I’m here again!
The time is passing so fast and when we decided to look to it we figure out that Java is already in version 13!
(YES 13)!!!
So, if you are familiar with one of the phrases below, this series is for you!
“Oh my God, I’m working with Java 6, what did I miss?”
“Yes, I know, I’m working with Java 8, but I only changed because I would like to use Lambda”
“Yes, I know, I’m working with Java 10, but only because is easy to migrate from 8 to 10”
“Yes, I know, I’m working with Java 13, but to be honest, I don’t know what changed, I only like to keep updated”
With the release of Java 13, some people called me to ask what the interesting things are in this new version (yes, because I’m a crazy guy that loves to follow Releases Notes).
Thinking about all those changes and with the goal to help more people, I had the idea to create this series that I simply called “The Java Recent History” to explain the most important changes that each version has and the complete link to all changes if you want to go deeper.
Note: I will base these articles on the official documentation, to make you more familiar with the next Releases Notes.
I hope you enjoy this time travel!
Thinking about my career, I started with Java 6 and my first Releases Notes was the Java 7 RN, so, I will start this series with the new features/enhancements of Java 7!
The JDK 7 was officially released on July 28, 2011, as you can check here and the official Release Notes are here.
For me, the JDK 7 was an important major release, that brought a lot of changes, not only in the Java Programming Language with the new try-catch-resource and MultiCatch but in the Java Virtual Machine (JVM) with the Garbage-First Collector (G1).
Now I’ll explain the most important changes that we have in Java 7.
- Garbage-First Collector
- try-with-resources Statement
- Multi Catch
- New Java I/O API
- Diamond Operator
- Rethrowing Exceptions with More Inclusive Type Checking
- Strings in switch Statements
- Underscores in Numeric Literals
- Binary Literals
Garbage-First Collector
The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories. It meets garbage collection (GC) pause time goals with a high probability while achieving high throughput. The G1 garbage collector is fully supported in Oracle JDK 7 update 4 and later releases.
The G1 collector is designed for applications that:
- Can operate concurrently with applications threads like the CMS collector
- Compact free space without lengthy GC induced pause times
- Need more predictable GC pause durations
- Do not want to sacrifice a lot of throughput performance
- That requires large heaps with limited GC latency. This means heap sizes of around 6GB or larger, and stable and predictable pause time below 0.5 seconds
How was the life Before Java 7?
Ok, good question!
The older garbage collectors (Serial, Parallel and CMS) all structure the heap with a fixed memory size into three regions:
- Young Generation (Eden + Survivor Spaces)
- Old Generation (Tenured)
- Permanent Generation (Permgen)
It means that for each region the memory is reserved and fixed!
Official Image used in the G1 Oracle’s documentation — Older Collectors
Hmm, cool, but now?
The Garbage-First (G1) divides heap memory into multiple regions/blocks, keeping the size of each block equal. It means that the heap is partitioned into a set of equal-sized heap regions, each with a contiguous range of virtual memory.
Certain region sets are assigned the same roles (eden, survivor, old) as in the older collectors, but there is not a fixed size for them.
This provides greater flexibility in memory usage.
Official Image used in the G1 Oracle’s documentation — G1 Collector
The JVM generally targets around 2000 regions varying in size from 1 to 32Mb.
When performing garbage collections, G1 operates in a manner similar to the CMS collector. G1 performs a concurrent global marking phase to determine the liveness of objects throughout the heap.
After the mark phase completes, G1 knows which regions are mostly empty and it collects in these regions first, which usually yields a large amount of free space.
This is why this method of garbage collection is called Garbage-First.
As the name suggests, G1 concentrates its collection and compaction activity on the areas of the heap that are likely to be full of reclaimable objects, that is, garbage.
Notes:
- It is important to note that G1 is not a real-time collector. It meets the set pause time target with high probability but not absolute certainty.
- Full garbage collections are still single-threaded, but if tuned properly your applications should avoid full GCs.
Try-with-resources Statement
The try-with-resources statement is a try statement that declares one or more resources.
A resource is an object that must be closed after the program is finished with it.
The try-with-resources statement ensures that each resource is closed at the end of the statement.
Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
Problems solved:
- If the developer forgets to close a resource, we have a memory leak
- You always need to check if the resource is null before closing it, to avoid NullPointerException
- Unnecessary Finally block. We are using the finally block only to close the resources
Advantages:
- Readability
- No need to close the resource manually. Resources will be implicitly closed after the try block, avoiding memory leak
- The management of the resource is implicit
Implementation:
private static void beforeJava7() {
SomeResource someResource = new SomeResource();
try {
someResource.start();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(someResource != null){
try {
someResource.close();
} catch (ArrayIndexOutOfBoundsException a){
a.printStackTrace();
}
}
}
}
private static void java7() {
try (SomeResource someResource2 = new SomeResource()) {
someResource2.start();
} catch (IOException | ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
}Multi Catch
In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.
Advantages:
- Simpler
- More readable
- Avoid code duplication (no redundancy)
Implementation:
private static void beforeJava7() {
try {
throwIllegalArgumentException();
} catch (IllegalArgumentException e) {
print(e);
} catch (NoSuchElementException e) {
print(e);
}
}
private static void java7() {
try {
throwNoSuchElementException();
} catch (IllegalArgumentException | NoSuchElementException | NullPointerException e) {
print(e);
}
}New Java I/O API
This new API was created to solve some issues around java.io.File.
Problems Before Java 7
- No proper exception handler
- Performance issues
- Verbose/Complex code
- Methods not consistent with all operating systems
- Missing basic file operations
- Limited support for file attribute
Advantages:
- No need to close resources explicitly
- Readable/Simple code
Implementation:
//Reading a File
private static void beforeJava7() {
FileInputStream fis = null;
String filename = "file.txt";
String content = "";
try {
File file = new File(NewIO.class.getClassLoader().getResource(filename).getFile());
fis = new FileInputStream(file);
int i;
while ((i = fis.read()) != -1) {
content += (char) i;
}
System.out.println(content);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
//Reading a File
private static void java7() {
try {
String filename = "file.txt";
Path path = Paths.get(NewIO.class.getClassLoader().getResource(filename).toURI());
String content = new String(Files.readAllBytes(path));
System.out.println(content);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
}Diamond Operator
You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context.
This pair of angle brackets is informally called the diamond.
Advantages:
- Avoid code redundancy
- The compiler infers the value of type arguments, simplifying the code
Implementation:
private static List<Map<String, List<String>>> beforeJava7 = new ArrayList<Map<String, List<String>>>();
private static List<Map<String, List<String>>> java7 = new ArrayList<>();Rethrowing Exceptions with More Inclusive Type Checking
The Java SE 7 compiler performs a more precise analysis of rethrown exceptions than earlier releases of Java SE.
This enables you to specify more specific exception types in the throws clause of a method declaration.
Advantages:
- You don’t need to specify the correct type of an exception you want to rethrow explicitly anymore, the compiler will take care of this for you!
Implementation:
private static void beforeJava7() throws RuntimeException {
try {
someMethodThatCanThrowsIllegalOrNoSuchElementException();
} catch (RuntimeException e) {
if (e instanceof IllegalArgumentException) {
throw new IllegalArgumentException();
} else {
throw new NoSuchElementException();
}
}
}
private static void java7() throws IllegalArgumentException, NoSuchElementException {
someMethodThatCanThrowsIllegalOrNoSuchElementException();
}Strings in switch Statements
Now we can use a String object in the expression of a switch statement. Yes, simply like that!
Implementation:
private static int getNumberByString(String string) {
int number;
switch (string) {
case "one":
number = 1;
break;
case "two":
number = 2;
break;
case "three":
number = 3;
break;
case "four":
number = 4;
break;
case "five":
number = 5;
break;
default:
number = 0;
}
return number;
}Underscores in Numeric Literals
Now we can use underscore characters ( _ ) between digits in a numerical literal.
So we can use, for example, to separate groups of digits in numeric literals, which improves the readability of the code.
The goal of this underscore is to improve the readability of the number, but there are some cases that we can not use it.
- At the beginning or end of a number
- Adjacent to a decimal point in a floating-point literal
- Prior to an F or L suffix
- In positions where a string of digits is expected
Implementation:
int beforeJava7 = 111000222;
int java7 = 111_000_222;Binary Literals
In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system.
To specify a binary literal, add the prefix 0b or 0B to the number.
Implementation:
// An 8-bit 'byte' value:
byte Byte = (byte) 0b00100001;
// A 16-bit 'short' value:
short aShort = (short) 0b1010000101000101;
// Some 32-bit 'int' values:
int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // The B can be upper or lower case.
// A 64-bit 'long' value. Note the "L" suffix:
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;Only this?
No, as I said the Java 7 was an important major release, and we had more changes, but I will not explain these changes because I want to focus on the most important changes IMHO, but I will list the link to the official documentation below!
- Swing
- Networking
- Security
- Concurrency Utilities
- Rich Internet Applications (RIA)/Deployment
- Requesting and Customizing Applet Decoration in Dragg able Applets
- Embedding JNLP File in Applet Tag
- Deploying without Codebase
- Handling Applet Initialization Status with Event Handlers
- Java 2D
- Java XML — JAXP, JAXB, and JAX-WS
- Internationalization
- java.lang Package
- Multithreaded Custom ClassLoaders in Java SE 7
- Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods
- Java Virtual Machine Support for Non-Java Languages
- Java HotSpot Virtual Machine Performance Enhancements
- JDBC
If you are reading this phrase, I would like to say thank you!
I hope this article could help you to understand the most important changes that we had in Java 7 and created a bit of curiosity about the next article, the most important changes in Java 8.
Oh, if you want to check the implementations and play with the code, you can check all implementations on the GitHub.
See you in the next article guys!
Comments
No comments yet. Be the first.