Exploring Java 8
This article summarizes the features added in Java 8. It covers the overall content, and more detailed information can be found in the attached related links.
Summary of New Features
Lambda Expression (a.k.a Anonymous Method)
The foundation of Java’s lambda expressions is based on ’lambda calculus’ proposed by Alonzo Church in the 1930s. It’s a formal system that abstracts function definition, function application, and recursive functions! For more details, refer to Lambda Calculus Wiki.
You can understand it as supporting anonymous method creation syntax.
Java7
| |
Java8
| |
In the existing Java, you had to create a thread, implement an anonymous class, and override the method. This structure forces class implementation even for simple code and generates unnecessary code. With lambda expressions, you can write code more simply and focus more on the code you originally intended to implement. Additionally, when implementing a ‘functional interface’, you don’t need to specify which method to override. I’ll explain functional interfaces in detail later.
Java7
| |
Java8
| |
Lambda expressions support ’type inference’, so the compiler can infer the type of parameters without explicitly declaring them. Since you don’t need to declare explicitly, the amount of code is reduced.
Stream API
The Stream API is an effective use of lambda expressions, providing a new mechanism for handling the Collection interface. Pipeline/lazy/parallel processing are provided through the same interface, enabling functional programming.
Referred to ’lambda-resort’ Github
| |
This logic creates a stream from a container, filters only guest objects with the same company, sorts by guest.grade in ascending order, extracts only guest names, and creates a list again. Parts that could be complex with existing for-each loops become simpler and clearer.
Calling parallelStream() instead of stream() gives you parallel processing too. But if the data isn’t large enough it can actually be slower, and mutating shared state like an ArrayList inside the lambda can break the result, so collect with collect() instead.
| |
Default Method
In Java’s rigid interface system, adding a method to an interface affects all implementations. Somewhere in the Concrete/Abstract Class implementing the interface, overriding is required.
Previously, this was resolved through various workarounds:
- Using helper classes
- Adding extension interfaces
- Extension through abstract classes, etc.
| |
The implementation of forEachRemaining doesn’t force implementation in inherited classes, leaving room for extension through overriding.
Implementation through inheritance takes precedence over interface default methods! (Override method > Default method)
Diamond Problem can occur!
| |
Can be avoided by explicitly defining which interface’s default method to use:
| |
Static methods can also be included in interfaces / No need to separate into utility classes:
| |
New Date API Based on Joda Time (JSR 310)
Problems with Basic Date Classes
The date-related classes provided in JDK until Java7 had many problems. Eventually, utility libraries like Joda Time emerged to resolve some issues, but the Java community officially proposed a new standard.
First, I’ve briefly summarized what problems existing date-related code could have. (This content was referenced from [3].)
Not immutable! Java’s Date/Calendar classes allow free modification of internal objects through Getter/Setter. Thread safety is not guaranteed, making it vulnerable to malicious code.
Constant misuse
| |
Even if you wanted to manipulate in seconds as in (1), writing as in (2) doesn’t cause an error during compilation. You can only recognize the logical error during runtime.
| |
You can set the date 1582-10-4 as in (1). Since ‘OCTOBER == October’ is generally recognized, if you don’t use constants and set with arbitrary integers, you may get different results than intended. The value of Calendar.OCTOBER constant is ‘9’, so setting it to 10 means setting it to November.
- Inconsistent day-of-week constants
Calendar.get(Calendar.DAY_OF_WEEK) represents Sunday as 1 (=Calendar.SUNDAY). On the other hand, if you get a Date object with calendar.getTime() and get the day of the week with Date.getDay() method, Sunday becomes 0.
Introduction to New Date Standard (JSR-310)
A new API for date and time was added with the JSR-310 standard. It was influenced by several open sources like Joda Time, Time And Money, and ICU.
| |
Improved Meta-annotation Support
Meta-programming is used for development convenience and productivity. It’s a development method where annotations are placed on methods or properties and information is dynamically retrieved. Java 8 added the ‘@Repeatable’ annotation, and annotations inherit Context. Almost everything can be expressed with annotations, including local variables, generic types, superclasses and interface implementations, and even method Exception definitions. For more details, refer to link [4].
| |
Concurrency API Improvements
- New methods added to java.util.concurrent.ConcurrentHashMap to support streams and lambda expressions
- java.util.concurrent.ForkJoinPool multi-core ExecutorService implementation (JDK7+) / ForkJoinPool.commonPool() method added so you can allocate without creating ForkJoinPool objects
- java.util.concurrent.locks.StampedLock was added to improve performance issues with java.util.concurrent.locks.ReadWriteLock. Not only is it faster by itself, but it also provides Optimistic Lock for even faster operation. See link [5] for details. See link [6] for performance comparison.
- Classes supporting atomic operations for counting/accumulation (DoubleAccumulator, DoubleAdder, LongAccumulator, LongAdder) were added. See link [5] for details.
- java.util.concurrent.CompletableFuture was added, so async tasks can be chained or combined with
thenApply,thenCombine, and so on. (The old Future only let you block on get().)
IO/NIO Extensions
Methods added to IO/NIO related classes / Usability improvements through Stream API
| |
Some of the added methods listed.
| |
Example listing files that don’t start with ‘.’ in the current directory.
java.util.Base64 class added
| |
Removal of Permanent Generation from Heap
Cause of java.lang.OutOfMemoryError: PermGen error. (PermGen is only cleaned up during a Full GC and has a fixed size. Causes are mainly indiscriminate Static variables + PermGen memory leaks due to HotSwap)
Changed JVM Options
PermGen related JVM options are now ignored, and new JVM options have been added.
- Removed JVM Options
| |
- Added JVM Options
| |
PermGen to Metaspace
Refer to the content summarized in link [7] for detailed changes.
Briefly summarized as follows:
Permanent until Java7
- Class Meta information (can be considered as pkg path information, text information)
- Method Meta information
- Static Object
- Constant String Object
- Array object Meta information related to class
- JVM internal objects and JIT optimization information
Metaspace and Heap separation in Java8
- Class Meta information -> Moved to Metaspace area
- Method Meta information -> Moved to Metaspace area
- Static Object -> Moved to Heap area
- Constant String Object -> Moved to Heap area
- Array object Meta information related to class -> Moved to Metaspace area
- JVM internal objects and JIT optimization information -> Moved to Metaspace area
In summary:
The heap changed from New / Survive / Old / Perm to New / Survive / Old, and the metadata that lived in Perm moved to Metaspace in native memory, not the heap.
Static Objects that were stored in PermGen area and caused problems were moved to Heap area to be GC targets as much as possible. (Static Final can’t be helped…)
Only information that doesn’t need to be modified is stored in Metaspace, and Metaspace has been improved to a structure where JVM can resize as needed.