References:
- "JDK 8 Release Notes" @ https://www.oracle.com/technetwork/java/javase/8all-relnotes-2226344.html.
- "What's New in JDK 8" @ http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html.
- OpenJDK's JDK 8 @ https://openjdk.java.net/projects/jdk8/.
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 with three big features:
- Lambda Expressions
- Stream API
- 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 @ https://docs.oracle.com/javase/tutorial/datetime/.
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 java.util.date
. 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 zoneZonedDateTime
: with time zoneInstant
: machine readable time representationPeriod
,Duration
:- Clock:
java.time.format
: Classes for formatting and parsing dates and times.java.time.zone
: Classes for time zones, time-zone offsets, and time zone rules (ZonedDateTime
, andZoneId
orZoneOffset
).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:
- Human Time: in terms of year, month, day, hour, minute and second.
- 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 = LocalDate.now(); 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 = LocalTime.now(); 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 = LocalDateTime.now(); System.out.println(dt1); // 2018-04-30T21:25:38.615116500 (default format 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 = LocalDateTime.now(ZoneId.of("America/Los_Angeles")); System.out.println(dt6); // 2018-04-30T06:50:00.419534 } }
The API's methods have standardized prefixes 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 toset
, 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 LocalDate/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 = Instant.now(); 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 = ZonedDateTime.now(); // 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
[TODO]
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 java.land.Long
class.
logicalAnd(), logicalOr(), logicalXor() in Boolean Wrapper Class
[TODO]
More utility methods in java.lang.Math class
int addExact(int x, int y)
: throwing an exception if the result overflows anint
.long addExact(long x, long y)
: throwing an exception if the result overflows anlong
.subtractExact()
,multiplyExact()
,incrementExact()
,decrementExact()
,negateExact()
: forint
andlong
.floorDiv()
,floorMod()
: forint
andlong
.int toIntExact(long value)
:nextDown(double)
,nextDown(float)
:
[TODO] Examples
Others
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
[TODO]
JDK 8 Concurrency API Improvements
[TODO]
REFERENCES & RESOURCES