JDK 8 New Features

  1. "JDK 8 Release Notes" @
  2. "What's New in JDK 8" @
  3. OpenJDK's JDK 8 @


JDK 8 is a MAJOR upgrade! It introduces new syntaxes (Lambda Expression) to support functional programming; retrofitted existing libraries (especially the Collection Framework); and added new libraries and features.

JDK 8 comes wiith three big features:

  1. Lambda Expressions
  2. Stream API
  3. Date/Time API (java.time)

JDK 8 Lambda Expressions and Functional Programming

See "Functional Programming and Lambda Expressions".

JDK 8 Date/Time API

References: The Java Tutorial: Date Time @

Prior to JDK 8, It has always been hard to work with date, time and time zones, because there is no standard approach or API for date and time. For example, we have Date class in both java.util (with both date and time) and java.sql (with date only) packages. Formatting and parsing classes are defined in java.text package. All the date classes are mutable, hence, they are NOT thread safe in multithreading. There is no internationalization support (such as time zone) in So, java.util.Calendar and java.util.TimeZone classes were introduced.

JDK 8 revamped the date-time support by introducing a new package java.time to provide a comprehensive support of dates, times, instants, durations, timezones, and periods. All the classes are immutable and thread safe for multithreading.

JDK 8 Date/Time API is comprehensive! It consists of main package java.time and four sub-packages:

  • java.time: Core API classes.
    • LocalDate, LocalTime, LocalDateTime: no time zone
    • ZonedDateTime: with time zone
    • Instant: machine readable time representation
    • Period, Duration:
    • Clock:
    These classes are based on ISO-8601 (Gregorian calendar system).
  • java.time.format: Classes for formatting and parsing dates and times.
  • Classes for time zones, time-zone offsets, and time zone rules (ZonedDateTime, and ZoneId or ZoneOffset).
  • java.time.temporal: Extended API for interoperations between the date and time classes, querying, and adjustment.
  • java.time.chrono: for calendar systems other than the default ISO-8601 (e.g., Thai Buddhist and Japanese), not commonly-used.

There are two ways to represent date-time, which are clearly separated in the new API:

  1. Human Time: in terms of year, month, day, hour, minute and second.
  2. Machine Time: in nanoseconds or days from an origin called epoch (1970-01-01T00:00:00Z)).

java.time by Examples

Example on Classes LocalDate, LocalTime, LocalDateTime

LocalXxx classes (such as LocalDate, LocalTime, LocalDateTime) represents a human readable date/time without timezone.

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.ZoneId;
public class TestLocalDateTime { public static void main(String[] args) { // Test LocalDate LocalDate d1 =; System.out.println(d1); // 2018-04-30 LocalDate d2 = LocalDate.of(2017, Month.JANUARY, 8); // year, month, day System.out.println(d2); // 2017-01-08 // Test LocalTime LocalTime t1 =; System.out.println(t1); // 21:24:24.699162200 LocalTime t2 = LocalTime.of(12, 34, 56, 123456); // hour, minute, second, nanosecond System.out.println(t2); // 12:34:56.000123456 // Test LocalDateTime LocalDateTime dt1 =; System.out.println(dt1); // 2018-04-30T21:25:38.615116500 (default foramt in ISO_LOCAL_DATE_TIME) // Test "Getters" LocalDateTime dt2 = LocalDateTime.of(2017, 2, 18, 23, 56, 45, 123456789); System.out.println(dt2); // 2017-02-18T23:56:45.123456789 System.out.println(dt2.getYear()); // 2017 System.out.println(dt2.getMonth()); // FEBRUARY (using enum java.time.Month) System.out.println(dt2.getDayOfMonth()); // 18 System.out.println(dt2.getHour()); // 23 System.out.println(dt2.getMinute()); // 56 System.out.println(dt2.getSecond()); // 45 System.out.println(dt2.getNano()); // 123456789 (nanosecond) System.out.println(dt2.getDayOfWeek()); // SATURDAY (using enum java.time.DayOfWeek) System.out.println(dt2.getDayOfYear()); // 49 // Test "Setters": DateTime classes are immutable. Return a new instance LocalDateTime dt2a = dt2.withYear(2018); System.out.println(dt2a); // 2018-02-18T23:56:45.123456789 LocalDateTime dt2b = dt2.withDayOfYear(365); System.out.println(dt2b); // 2017-12-31T23:56:45.123456789 // Test Output Formatter LocalDateTime dt3 = LocalDateTime.of(2017, 2, 18, 23, 56, 45); // Using formatter with pre-defined constant System.out.println(dt3.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2017-02-18 // Using formatter with pattern DateTimeFormatter f1 = DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss"); // HH for 24-hour clock, kk for 12-hour clock System.out.println(dt3.format(f1)); // 18-Feb-2017 11:56:45 // Test Input Parser LocalDateTime dt4 = LocalDateTime.parse("2017-05-02T23:15:43.967"); System.out.println(dt4); // 2017-05-02T23:15:43.967 LocalDateTime dt5 = LocalDateTime.parse("18-Feb-2017 11:56:45", f1); System.out.println(dt5); // 2017-02-18T11:56:45 // You can also create the current date/time specifying a timezone. LocalDateTime dt6 ="America/Los_Angeles")); System.out.println(dt6); // 2018-04-30T06:50:00.419534 } }

The API's methods have standardized perfixes as follows:

  • now: static factory method for creating an instance of current date, time.
  • of: static factory methods for creating an instance.
  • getXxx: get an attribute.
  • withXxx: returns a copy of the target object with one element changed. Similar to set, but all date-time classes are immutable.
  • parse: static factory methods for parsing the input string to produce an instance.
  • format: using the formatter to produce a string.
  • is: query the state.
  • plus, minus: returns a copy with the amount of time added or subtracted.
  • to: convert to another type.
  • at: combine with another.
Example on Date/Time Utilities

The LcoalDate/LocalTime/LocalDateTime classes provide various utility methods such as plusXxx(), minusXxx(). There are some other utility methods for adjusting the date using TemporalAdjuster and to calculate the Period between two dates. For example,

import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.TemporalAdjusters;

public class TestDateTimeCalculation {
   public static void main(String[] args) {
      LocalDate d1 = LocalDate.of(2000, 1, 23);
      System.out.println(d1);  // 2000-01-23

      System.out.println(d1.isLeapYear());   // true
      System.out.println(d1.isBefore(LocalDate.of(2000, 12, 30))); // true
      System.out.println(d1.isAfter(LocalDate.of(2000, 12, 30)));  // false
      System.out.println(d1.plusDays(2));    // 2000-01-25
      System.out.println(d1.plusWeeks(4));   // 2000-02-20
      System.out.println(d1.plusMonths(6));  // 2000-07-23
      System.out.println(d1.plusYears(8));   // 2008-01-23
      System.out.println(d1.minusDays(2));   // 2000-01-21
      System.out.println(d1.minusWeeks(4));  // 1999-12-26
      System.out.println(d1.minusMonths(6)); // 1999-07-23
      System.out.println(d1.minusYears(8));  // 1992-01-23

      LocalDate d2 = d1.with(TemporalAdjusters.firstDayOfMonth());
      System.out.println(d2);  // 2000-01-01
      LocalDate d3 = d1.with(TemporalAdjusters.lastDayOfYear());
      System.out.println(d3);  // 2000-12-31

      Period p1 = d1.until(d2.plusYears(10));
      System.out.println(p1);  // P9Y11M9D (period of 9 Years 11 months 9 days)
Example on Class Instant, Duration

The Instant class is used to work with machine readable time format, it stores date time in Unix timestamp. The Duration class models a quantity or amount of time in terms of seconds and nanoseconds (whereas Period in the previous example expressed in days, months and years).

import java.time.Instant;
import java.time.Duration;

public class TestInstant {
   public static void main(String[] args) {
      Instant t1 =;
      System.out.println(t1);  // 2018-04-30T14:30:12.213617900Z
      long epochSecond = t1.getEpochSecond();
      System.out.println(epochSecond);  // 1525098612

      Instant t2 = Instant.ofEpochSecond(epochSecond + 86400);  // a day
      System.out.println(t2);  // 2018-05-01T14:30:12Z

      Duration d1 = Duration.ofDays(15);
      System.out.println(d1);  // PT360H
      System.out.println(d1.getSeconds());  // 1296000
Example of ZonedDateTime

The ZonedDateTime represent a date/time with a timezone. (There are no ZonedDate or ZonedTime classes.)

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class TestZonedDateTime {
   public static void main(String[] args) {
      ZonedDateTime dt1 =;  // in default timezone
      System.out.println(dt1);  // 2018-04-30T23:24:38.476241100+08:00[Asia/Singapore]

      ZonedDateTime dt2 = ZonedDateTime.of(2000, 1, 2, 3, 4, 5, 6, ZoneId.of("America/Los_Angeles"));
      System.out.println(dt2);  // 2000-01-02T03:04:05.000000006-08:00[America/Los_Angeles]

Compared with LocalDateTime, ZonedDateTime clearly maintains the time zone.

Enum java.time.DayOfWeek and java.time.Month

Enum DayOfWeek

For representing day of the week, with 7 constants MONDAY (1) through SUNDAY (7) and various operations.

Enum Month

For representing month names, with 12 constants JANUARY (1) through DECEMBER (12) and various operations.

JDK 8 Library Change

min(), max(), sum() in Integer, Long and Double Wrapper Classes


Unsigned int and long Support

JDK 8 does not introduce a C-like new type "unsignedInt". But it added new methods in Integer and Long classes to treat an int and long as unsigned integer.

For example,

public class TestUnsignedInteger {
   public static void main(String[] args) {
      // Pr-JDK 8
      // 32-bit signed int ranges from −2,147,483,648 −(2^31) to 2,147,483,647 (2^31 – 1)
      System.out.println(Integer.parseInt("2147483647"));  // max 32-bit unsigned integer
      System.out.println(Integer.parseInt("-2147483648")); // min 32-bit unsigned integer
      //System.out.println(Integer.parseInt("2147483648"));  // error: NumberFormatException

      // JDK 8
      // 32-bit unsigned int ranges from 0 to 4,294,967,295 (2^32 – 1)
      int i1 = Integer.parseUnsignedInt("4294967295");  // max 32-bit unsigned integer
      System.out.println(i1);   // -1 (treated as signed int)
      System.out.println(Integer.toUnsignedString(i1));  // 4294967295
      System.out.println(Integer.toUnsignedString(-1));  // 4294967295

      long l1 = Long.parseUnsignedLong("18446744073709551615");  // max 64-bit unsigned integer
      System.out.println(l1);  // -1 (treated as signed long)
      System.out.println(Long.toUnsignedString(l1));  // 18446744073709551615
      System.out.println(Long.toUnsignedString(-1));  // 18446744073709551615

JDK 8 added these static methods in the java.lang.Integer class to deal with unsigned integers:

  • static int compareUnsigned(int x, int y): treat x and y as unsigned.
  • static int divideUnsigned(int dividend, int divisor):
  • static int remainderUnsigned(int dividend, int divisor):
  • static int parseUnsignedInt(...):
  • static String toUnsignedString(int i):

Similar static methods were also added in the class.

logicalAnd(), logicalOr(), logicalXor() in Boolean Wrapper Class


More utiltiy methods in java.lang.Math class

  • int addExact​(int x, int y): throwing an exception if the result overflows an int.
  • long addExact​(long x, long y): throwing an exception if the result overflows an long.
  • subtractExact​(), multiplyExact​(), incrementExact​(), decrementExact​(), negateExact​(): for int and long.
  • floorDiv​(), floorMod​(): for int and long.
  • int toIntExact​(long value):
  • nextDown​(double), nextDown​(float):

[TODO] Examples


  • jjs command is added to invoke Nashorn JavaScript Engine.
  • jdeps command is added to analyze class files.
  • JDBC-ODBC Bridge has been removed.

JDK 8 IO Improvements


JDK 8 Concurrency API Improvements