0% found this document useful (0 votes)
25 views

Java8 Features

Java 8 features
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views

Java8 Features

Java 8 features
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

ItsRunTym

JAVA 8 Features

Java 8 Features
1. Lambda Expressions
2. Functional Interfaces
3. Streams API
4. Default and Static Methods in Interfaces
5. Optional Class
6. Date and Time API (java.time package)
7. Nashorn JavaScript Engine
8. Method References
9. Collectors Class
10.Concurrency Enhancements
11.Comparable and Comparator
12.Annotations on Java Types
13.Repeating Annotations
14.New JavaFX Features
15.Enhanced Security Features
16.Parallel Array Sorting
17.Base64 Encoding and Decoding
18.PermGen Space Removal
19.Java Mission Control (JMC)
20.Compact Profiles
21.Unsigned Arithmetic Operations

1. Lambda Expressions

• Lambda expressions enable functional programming in Java by allowing


you to write inline implementation of functional interfaces, reducing
boilerplate code.
• They facilitate the use of concise syntax for expressing instances of
single-method interfaces.
• Lambda expressions are particularly useful in stream processing, event
handling, and parallel programming.
• They promote cleaner and more readable code by focusing on the "what"
(behavior) rather than the "how" (implementation details).

Java Lambda Expression Syntax

(argument-list) -> {body}

Example:

java

// Before Java 8
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello from a runnable!");
}
};

// Java 8 Lambda Expression


Runnable r2 = () -> System.out.println("Hello from a
lambda runnable!");

r1.run();
r2.run();

2. Functional Interfaces

• Functional interfaces have exactly one abstract method, making them


suitable for use with lambda expressions.
• They can include default methods, which provide default
implementations that can be overridden by implementing classes.
• Java 8 introduced static methods in interfaces to provide utility methods
that are tightly related to the interface's purpose.
• Functional interfaces are foundational to Java's support for functional
programming, enabling the use of lambda expressions and method
references.
• The @FunctionalInterface annotation can be used to mark an interface
as a functional interface.
Example:

java

@FunctionalInterface
interface MyFunctionalInterface {
void doSomething();
}

MyFunctionalInterface myFunc = () ->


System.out.println("Doing something!");
myFunc.doSomething();

3. Streams API

Streams provide a declarative way to process sequences of elements.

They support functional-style operations such as map, filter, reduce, and


collect, which can be pipelined to operate on large data sets.

Streams can be sequential or parallel, leveraging multicore architectures for


improved performance.

Introduced in Java 8, streams encourage concise and readable code for data
manipulation and transformation tasks.

Example:

java

import java.util.Arrays;
import java.util.List;

List<String> names = Arrays.asList("John", "Jane",


"Jack", "Doe");

names.stream()
.filter(name -> name.startsWith("J"))
.map(String::toUpperCase)
.forEach(System.out::println);

4. Default and Static Methods in Interfaces


Default methods allow interface creators to add new methods to interfaces
without breaking existing implementations.

Static methods in interfaces provide utility methods that can be called


directly on the interface itself.

These features were introduced in Java 8 to enhance interface flexibility and


backward compatibility.

Default and static methods enable the development of more robust and
reusable code in Java APIs.

Example:

java

interface MyInterface {
default void defaultMethod() {
System.out.println("This is a default
method");
}

static void staticMethod() {


System.out.println("This is a static
method");
}
}

class MyClass implements MyInterface {


// No need to override defaultMethod
}

MyClass obj = new MyClass();


obj.defaultMethod();
MyInterface.staticMethod();

5. Optional Class

The Optional class in Java is used to represent a value that may or may not
be present.

It helps prevent null pointer exceptions by encouraging explicit handling of


null values.
Optional provides methods like isPresent(), orElse(), and orElseThrow() to
safely access and manipulate potentially null values.

Introduced in Java 8, Optional promotes better coding practices by making


the presence or absence of values explicit in the code.

Example:

java

import java.util.Optional;

Optional<String> optional = Optional.of("Hello");

optional.ifPresent(System.out::println); // Prints
"Hello"
System.out.println(optional.orElse("Default")); //
Prints "Hello"

Optional<String> emptyOptional = Optional.empty();


System.out.println(emptyOptional.orElse("Default"));
// Prints "Default"

6. Date and Time API

Java's java.time package introduced in Java 8 provides comprehensive date


and time handling capabilities.

It includes classes like LocalDate, LocalTime, LocalDateTime, Instant,


Duration, and Period for date manipulation and formatting.

java.time classes are immutable and thread-safe, promoting safer concurrent


programming practices.

The API addresses shortcomings of the earlier java.util.Date and


java.util.Calendar classes, offering clearer and more intuitive date and time
operations.

Example:

java

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

LocalDate date = LocalDate.now();


LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");

System.out.println(date); // Prints current date


System.out.println(dateTime.format(formatter)); //
Prints current date and time

7. Nashorn JavaScript Engine

Nashorn is a lightweight JavaScript engine introduced in Java 8, enabling


seamless integration of JavaScript with Java applications.

It allows scripting capabilities within Java applications, facilitating dynamic


scripting and extension of Java applications with JavaScript logic.

Nashorn supports ECMAScript 5.1 specification and provides


interoperability between Java and JavaScript code.

The engine can be embedded in Java applications to execute JavaScript code


dynamically at runtime.

Example:

java

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

ScriptEngineManager manager = new


ScriptEngineManager();
ScriptEngine engine =
manager.getEngineByName("nashorn");

try {
engine.eval("print('Hello from JavaScript')");
} catch (ScriptException e) {
e.printStackTrace();
}
8. Method References

Method references provide a shorthand notation for lambda expressions to


invoke methods.

They can refer to static methods, instance methods, constructors, and


arbitrary object methods using different syntax (::).

Method references improve code readability by reducing verbosity,


especially for lambda expressions that simply call existing methods.

Introduced in Java 8, method references enhance the expressiveness and


flexibility of functional programming in Java.

Example:

java

import java.util.Arrays;

String[] names = {"John", "Jane", "Jack", "Doe"};


Arrays.sort(names, String::compareToIgnoreCase);
System.out.println(Arrays.toString(names)); //
Prints sorted names

9. Collectors Class

The Collectors class in Java provides utility methods for transforming


elements of a stream into various data structures (like lists, sets, and maps) or
performing aggregations.

It supports common reduction operations such as grouping, partitioning, and


joining elements.

Collectors facilitate efficient and concise data processing with streams by


encapsulating complex reduction operations.

This class is essential for stream operations involving grouping,


summarization, and collecting results into collections or aggregating values.

Example:

java

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

List<String> names = Arrays.asList("John", "Jane",


"Jack", "Doe");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("J"))
.collect(Collectors.toList());

System.out.println(filteredNames); // Prints [John,


Jane, Jack]

10. Concurrency Enhancements

Java provides several enhancements for concurrent programming, including


the java.util.concurrent package introduced in Java 5.

Features like ExecutorService, ConcurrentHashMap, CountDownLatch, and


Semaphore support efficient and thread-safe concurrent operations.

Java 8 introduced CompletableFuture for asynchronous programming,


offering a higher-level abstraction for handling asynchronous tasks.

These enhancements simplify concurrent programming in Java, improving


scalability and responsiveness of multi-threaded applications.

Example:
java

import java.util.concurrent.CompletableFuture;

CompletableFuture.supplyAsync(() -> "Hello")


.thenApplyAsync(result -> result + " World")
.thenAcceptAsync(result ->
System.out.println(result));

11. Comparable & Comparator

Comparable

The Comparable interface is used to define the natural ordering of objects. It has
a single method, compareTo, which compares the current object with another
object of the same type.
Example:
java

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Student implements Comparable<Student> {


private String name;
private int age;

public Student(String name, int age) {


this.name = name;
this.age = age;
}

public String getName() {


return name;
}

public int getAge() {


return age;
}

@Override
public int compareTo(Student other) {
return Integer.compare(this.age, other.age); //
Compare based on age
}

@Override
public String toString() {
return name + " (" + age + ")";
}

public static void main(String[] args) {


List<Student> students = new ArrayList<>();
students.add(new Student("John", 25));
students.add(new Student("Jane", 22));
students.add(new Student("Jack", 28));
students.add(new Student("Doe", 20));

Collections.sort(students);
System.out.println(students); // Output: [Doe
(20), Jane (22), John (25), Jack (28)]
}
}

Comparator

The Comparator interface is used to define multiple ways of sorting objects.


Java 8 introduced default and static methods to make it easier to chain and
create comparators.

Example:
java

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

List<String> names = Arrays.asList("John", "Jane",


"Jack", "Doe");

// Using Comparator with method references and chaining


names.sort(Comparator.comparing(String::length).thenCompa
ring(String::compareToIgnoreCase));

System.out.println(names); // Output: [Doe, Jack, Jane,


John]

Key Points

• Comparable: Defines natural ordering. Implemented within the class to


compare instances.
• Comparator: Defines custom ordering. Can be used to create multiple
sorting sequences and does not modify the class.

12. Annotations on Java Types

Annotations provide metadata about Java code, which can be used by the
compiler or at runtime.

Annotations on types (classes, interfaces, enums) are used to provide


additional information or behavior to the types.

Examples include @Override (ensures that a method overrides a superclass


method), @Deprecated (marks a method or class as obsolete), and custom
annotations for framework-specific or application-specific behavior.
Annotations enhance code readability, maintainability, and provide a way to
convey semantics or constraints to the Java compiler or runtime environment.

Example:
java

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(ElementType.TYPE_USE)
@interface MyAnnotation {}

public class Example {


@MyAnnotation String myString;
}

13. Repeating Annotations

Java 8 introduced repeating annotations, allowing an annotation to be


applied multiple times to the same element.

They are useful when multiple instances of the same annotation need to be
associated with a program element, such as specifying multiple roles or
permissions for a method or class.

Repeating annotations are declared using a container annotation that


specifies @Repeatable and holds the repeated annotation type.

This feature simplifies annotation usage and improves code clarity by


reducing the need for container annotations or complex metadata structures.

Example:
java

import java.lang.annotation.*;

@Repeatable(MyAnnotations.class)
@interface MyAnnotation {
String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotations {
MyAnnotation[] value();
}

@MyAnnotation("First")
@MyAnnotation("Second")
public class Example {}

public class Main {


public static void main(String[] args) {
MyAnnotation[] annotations =
Example.class.getAnnotationsByType(MyAnnotation.class);
for (MyAnnotation annotation : annotations) {
System.out.println(annotation.value());
}
}
}

14. New JavaFX Features

JavaFX is a platform for creating rich internet applications (RIAs) and GUI
applications in Java.

New features introduced in JavaFX include improved CSS styling


capabilities, support for web components, enhanced 3D graphics rendering, and
integration with modern UI controls.

JavaFX provides a rich set of APIs for multimedia, animation, and user
interface development, making it suitable for building modern desktop and
mobile applications.

JavaFX continues to evolve with updates and enhancements to support latest


Java versions and improve user experience in Java-based applications.

15. Enhanced Security Features

Java continuously enhances security features to protect applications from


vulnerabilities and malicious attacks.

Features include improved TLS support, stronger encryption algorithms, and


security provider enhancements.

Security enhancements also cover permissions and access control


mechanisms for Java applications running in different environments.

Java updates regularly address security vulnerabilities and provide guidelines


for secure coding practices to safeguard applications and data.
16. Parallel Array Sorting

Java 8 introduced parallel sorting for arrays, utilizing multiple threads for
faster sorting of large arrays.

The Arrays.parallelSort() method divides the array into smaller parts and
sorts them concurrently using the Fork/Join framework.

Parallel array sorting improves sorting performance on multi-core processors


by leveraging parallelism.

It is suitable for sorting operations where the data set is large and sorting can
be done independently on different segments of the array.

Example:
java

import java.util.Arrays;

int[] array = {5, 3, 8, 1, 2};


Arrays.parallelSort(array);
System.out.println(Arrays.toString(array)); // Output:
[1, 2, 3, 5, 8]

17. Base64 Encoding and Decoding

Java provides built-in support for Base64 encoding and decoding through
classes in the java.util package.

java.util.Base64 class provides methods to encode binary data (bytes) into a


Base64 encoded string and decode Base64 encoded strings back to binary data.

Base64 encoding is used for encoding binary data into text format, which is
useful for transmitting data over text-based protocols like HTTP.

Java's Base64 support simplifies encoding and decoding operations, ensuring


interoperability and data integrity in Java applications.

Example:
java

import java.util.Base64;

String original = "Hello, World!";


String encoded =
Base64.getEncoder().encodeToString(original.getBytes());
String decoded = new
String(Base64.getDecoder().decode(encoded));

System.out.println(encoded); // Output:
SGVsbG8sIFdvcmxkIQ==
System.out.println(decoded); // Output: Hello, World!

18. PermGen Space Removal

PermGen (Permanent Generation) was a part of Java's memory model used


to store class metadata and interned strings.

Starting from Java 8, PermGen space was removed and replaced with the
Metaspace to improve memory management and reduce issues related to
PermGen space exhaustion.

Metaspace dynamically adjusts its size based on the application's class


metadata requirements, reducing the risk of OutOfMemoryError caused by
PermGen space limitations.

This change enhances Java application performance and stability by


providing more flexible and efficient memory management for class metadata.

19. Java Mission Control (JMC)

Java Mission Control is a tool for monitoring, managing, and profiling Java
applications.

It provides real-time and historical data about JVM performance, memory


usage, threads, and garbage collection.

JMC enables developers and administrators to analyze application behavior,


diagnose performance issues, and optimize JVM settings.

It includes features like Flight Recorder for capturing detailed runtime


information and Mission Control Client for visualizing and analyzing JVM data.

20. Compact Profiles

Compact Profiles in Java provide subsets of the Java SE platform tailored for
different deployment scenarios.
They include selected APIs necessary for specific application types or
devices, reducing the footprint and improving startup time of Java applications.

Compact Profiles help optimize resource usage in embedded systems, IoT


devices, and environments with limited memory and processing power.

Java SE 8 introduced three compact profiles (Compact 1, 2, and 3) to


provide flexibility in deploying Java applications across diverse platforms and
devices.

21. Unsigned Arithmetic Operations

Java traditionally does not support unsigned data types (like unsigned int)
found in some other programming languages.

Unsigned arithmetic operations can be simulated using larger signed data


types (e.g., using long for unsigned int).

Java 8 introduced methods in Integer, Long, Short, and Byte classes to


support conversion and manipulation of unsigned values.

This enables Java programmers to perform bitwise and arithmetic operations


on unsigned integers with improved compatibility and performance.

Example:
java

int a = -1;
System.out.println(Integer.toUnsignedString(a)); //
Output: 4294967295

You might also like