Java New Features-Unit-3[1]
Java New Features-Unit-3[1]
Topics to be covered:
2
Java 8 Features
Oracle released a new version of Java as Java 8 in March 18, 2014. It was a revolutionary release of the Java for
software development platform. It includes various upgrades to the Java programming, JVM, Tools and
libraries.
•Lambda expressions,
•Method references,
•Functional interfaces,
•Stream API,
•Default methods,
•Base64 Encode Decode,
•Static methods in interface,
•Optional class,
•Collectors class,
•ForEach() method,
•Nashorn JavaScript Engine,
•Parallel Array Sorting,
•Type and Repeating Annotations,
•IO Enhancements,
•Concurrency Enhancements,
•JDBC Enhancements etc.
3
Lambda Expressions
Lambda expressions were introduced in Java 8 and represent a significant
enhancement to the Java programming language. A lambda expression
provides a clear and concise way to represent one method interface using
an expression.
Definition: A lambda expression in Java is a short block of code which takes
in parameters and returns a value. Lambda expressions are similar to
methods, but they do not need a name and can be implemented right in
the body of a method.
•Not having any name
•Not having any return type
•Not having any modifier
Syntax:(parameters) -> { statements; } or(parameters) -> expression;
4
Normal Function Lambda Expression
Key Characteristics:
8
@FunctionalInterface annotation:
• @FA is used to confirm that this interface is a functional interface and it will
definitely have one abstract method.
• If remove @FIA, and already given static or default method but not abstract
method, then it will give an exception. Because Functional interface can have
static, default method but also have abstract method. Also must not have
more than one abstract method.
• It can have any number of static, default method but only one abstract
method.
@FunctionalInterface
interface MyFunctionalInterface {
static void myMethod() {
System.out.println("hello");
}
}
// Give error as found no abstract method 9
Valid example of a functional interface
@FunctionalInterface
interface MyFunctionalInterface {
void abrst(); // Single Abstract Method (Required)
This is a valid functional interface, because it: Has only one abstract method. Includes static and default
methods, which are allowed.
10
Example of using a functional interface with a lambda expression:
A FA can be implemented using Lambda expression which provides a concise way to represent an instance of the object.
• Has a Default Implementation: Unlike abstract methods, it has a method body. So, it provides a default
behavior.
• Optional to Override: Classes that implement the interface can use the default method as-is, or Override it
if different behavior is needed.
18
Static Method
• A method that belongs to the class rather than any instance of the class.
• Ie. We can call a static method without creating an object of the class.
• Static methods are defined using the static keyword & static methods cannot be
overridden by subclasses.
public interface MyInterface {
static void staticMethod() {
System.out.println("Static method in interface."); } }
21
Traditional ‘switch’ Statement
Definition: A text block is a multiline string literal that enhances the readability
and ease of writing strings that span multiple lines.
Purpose: Simplifies writing and maintaining multiline strings.
Before Java 13:Multiline strings required concatenation or escape sequences.
Java 13 and Beyond:Text blocks were introduced to simplify multiline string
handling.
• Opening and Closing: Use triple double
Syntax of Text Blocks
quotes (""") to start and end a text block.
Example: • Newlines: Preserved as-is, so line breaks
String textBlock = """ appear in the string exactly as written.
This is a text block. • Indentation: Leading whitespace is ignored,
It spans multiple lines. which makes formatting easier and cleaner.
It is easy to read and maintain.
"""; Used within HTML, JSON, SQL, or any multiline content directly inside Java
27
code.
Traditional Way vs. Text Block
Traditional Way:
• Requires manual \n for line breaks.
String query = "SELECT * FROM users\n" + • Needs string concatenation (+) for
"WHERE age > 25\n" + multiline formatting.
"ORDER BY name;"; • Harder to read and maintain.
28
Java program demonstrating the use of text blocks
31
Records
• Records are a special kind of class in Java designed to model
immutable data carriers with a fixed set of fields.
• Used when want to store data in java that not needed to be
changed.
• Purpose: Provide a concise syntax to create data classes with
automatic implementations of common methods.
Features/ key benefits of Records
• Immutable: Fields are final and cannot be changed once set.
• Concise Syntax: Reduces boilerplate code for data classes.
• Automatic Methods: Generates constructor, getter, equals(),
hashCode(), and toString() methods.(these were to be created in
traditional classes). 32
Comparison between a traditional Java class and a Java record
Traditional Class
public class Person { Record
private final String name;
private final int age; record Person(String name, int age) { }
public Person(String name, int age) {
this.name = name;
this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
@Override
public boolean equals(Object o) {
return false; }
@Override
public int hashCode() {
return age; }
@Override
public String toString() {
return name;
}} 33
Key Differences:
38
Sealed Classes
It is a class that limits or restricts which other classes can extend it.
In simple words, we decide which specific subclasses are allowed.
47
Example:
List<String> list = Arrays.asList("A", "B", "C");
// Arrays.asList() is a static method in Java's java.util.Arrays class. Its purpose is:"To convert an array into a
list"
list.forEach(element -> System.out.println(element));
//This code prints each element in the list using a lambda expression. Here element is an
iterator that goes to each item in the list and then print. Example: forEach
Traditionally, it work like this: import java.util.Arrays;
for(String element : list) { import java.util.List;
System.out.println(element); public class ForEachExample {
} public static void main(String[] args) {
List<String> items = Arrays.asList("Apple", "Banana",
"Cherry", "Date");
Output: // Using forEach with a lambda expression
Apple Fruits items.forEach(item -> System.out.println(item + "
Banana Fruits
Cherry Fruits
Fruits"));
Date Fruits }} 48
Base64 encoding and decoding
import java.util.Base64;
Example: public class Base64Example {
public static void main(String[] args) {
// Step 1: Original String
String original = "Hello Java!";
// Step 2: Encode the String using Base64
String encoded = Base64.getEncoder().encodeToString(original.getBytes());
System.out.println("Encoded String: " + encoded);
// Step 3: Decode the Base64 string back to original
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes);
System.out.println("Decoded String: " + decoded);
}
}
50
Step-by-Step Explanation:
51
try-with-resources
• is a try statement that is used for declaring one or more
resources such as streams, sockets, DBs, connections,
etc.
• also referred as "Automatic Resource Management and it
was introduced in Java7.
• It simplifies resource handling by automatically closing
resources after they are no longer needed, preventing
try(resources declarations) {
resource leaks and reducing //boilerplate code.
use of the resources
Syntax:
}
catch(Exception e) {
// exception handling
} 52
Main Points:
import java.io.FileReader;
import java.io.IOException;
public class Try_withDemo {
public static void main(String args[]) {
try(FileReader fr = new FileReader(“D://file1.txt")) {
char [] a = new char[50];
fr.read(a); // reads the contentto the array
for(char c : a)
System.out.print(c); // prints the characters one by one
} catch (IOException e) {
e.printStackTrace();
} } }
54
Example 2: Try with Resources having Multiple Resources
{
import java.io.BufferedReader;
String line;
import java.io.FileReader;
while ((line =
import java.io.FileWriter;
bufferedReader.readLine()) != null)
import java.io.PrintWriter;
{
import java.io.IOException; // Read content line by line and write it
public class Main { to the output (file2.txt) file
public static void main(String[] args) { printWriter.println(line);
// try block with multiple resources }
try ( System.out.println("Content
FileReader fileReader = new FileReader("file1.txt"); copied.");
BufferedReader bufferedReader = new } catch (IOException e) {
BufferedReader(fileReader); e.printStackTrace();
FileWriter fileWriter = new FileWriter("file2.txt"); } } }
PrintWriter printWriter = new PrintWriter(fileWriter)
)
55
Annotations
• Are special kinds of metadata added to Java code. They provide
information to the compiler or JVM but do not change the actual logic
of the program.
• They are always prefixed with @, like @Override.
Use of Annotations:
• To give instructions to the compiler.
• To help tools and frameworks (like Spring, Hibernate).
• To provide runtime information.
• Commonly used for configuration, Documentation and Debugging
Common Built-in Annotations in Java
1. @Override(Indicates that a method overrides a method from a superclass)
2. @Deprecated(Marks a method or class as outdated)
3. @ SuppressWarnings(Tells the compiler to ignore warnings.) 56
Ex. @Deprecated
class Animal {
void sound() { class OldCode {
Ex.
@Override System.out.println("Animal @Deprecated
sound"); } } void oldMethod() {
System.out.println("Old method");
class Dog extends Animal { }
@Override }
void sound() {
System.out.println("Bark"); } }
import java.util.*;
Ex. class Example {
@SuppressWarnings
@SuppressWarnings("unchecked")
void myMethod() {
List list = new ArrayList(); // unchecked warning suppressed
}}
57
Type Annotations
Definition: Type annotations are annotations that can be applied to
any use of a type, including type declarations, type casts, and type
parameters.
Get introduced in Java 8, allow annotations to be used anywhere a
type is used.
Purpose: Provide additional information to the compiler and tools to
improve code quality and enable advanced features.
58
public class TypeAnnotationExample {
public void process(@NonNull String input) {
// Method implementation
}}
@NonNull is a type annotation which tells that values of input or names must
not be null. Provide additional information to the compiler and tools to improve
code quality and enable advanced features.
59
Program on custom @NonNull annotation
(We do null check manually because annotation do not check themselves, we have to check manually)
69
Traditional way and the Stream API approach to iterate over a list:
70
Example: Create a Stream and Print Each Element
import java.util.Arrays;
import java.util.List;
71
Three simple ways to create a Stream
1. Create Stream from a List
List<String> items = Arrays.asList("apple", "banana", "cherry");
Stream<String> list2 = items.stream(); //Use .stream() method from a List.
import java.util.Arrays;
Import: import java.util.List;
import java.util.stream.Stream; 72
Stream Operations
Stream Operations are divided into two categories:
75
Terminal Operations Programs
A) ForEach Operation: Performs an action for each element of the stream.
List<String> items = Arrays.asList("apple", "banana", "cherry");
items.stream()
.forEach(System.out::println);
B) collect operation: accumulate elements into a collection (like a List, Set, or Map).:
List<String> items = Arrays.asList("apple", "banana", "cherry");
List<String> result = items.stream()
.collect(Collectors.toList());
System.out.println(result); // Output: [apple, banana, cherry]
java --list-modules
This command lists all the Java Platform built-in Modules available in the current JDK.
https://www.youtube.com/watch?v=M4Ek1qHTky4
77
Key Concepts
Keyword Meaning
module Declares a module
requires Specifies dependencies on other modules
exports Makes a package accessible to other modules
78
Directory Structure:
Module A: (Provides a service) - moduleA/module-info.java
module moduleA {
exports com.a; }
moduleA/com/a/HelloA.java
package com.a;
79
Module B: (Depends on Module A) moduleB/com/b/MainB.java
package com.b;
moduleB/module-info.java
import com.a.HelloA;
module moduleB {
requires moduleA; public class MainB {
} public static void main(String[] args) {
HelloA obj = new HelloA();
Compilation and Execution obj.sayHello();
} }