0% found this document useful (0 votes)
3 views33 pages

java unit 3

This document provides an overview of new features and enhancements in Java from version 8 onwards, focusing on functional programming concepts like Functional Interfaces, Lambda Expressions, and the Stream API. It also discusses additional features such as Method References, Default and Static Methods in Interfaces, Base64 Encoding/Decoding, and Java Annotations. The content is derived from an educational video and includes definitions, examples, and practical applications of these features.

Uploaded by

Sneha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views33 pages

java unit 3

This document provides an overview of new features and enhancements in Java from version 8 onwards, focusing on functional programming concepts like Functional Interfaces, Lambda Expressions, and the Stream API. It also discusses additional features such as Method References, Default and Static Methods in Interfaces, Base64 Encoding/Decoding, and Java Annotations. The content is derived from an educational video and includes definitions, examples, and practical applications of these features.

Uploaded by

Sneha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 33

Detailed Briefing: Java Unit 3 - New

Features and Enhancements


This document provides a comprehensive overview of the new features
and enhancements in Java, primarily focusing on additions from Java 8
onwards. The source, an educational video, details these features with
definitions, explanations, examples, and practical applications.

1. Introduction to New Features in Java

The video begins by defining "features" as the inclusion or display of


something new and important within an existing entity. Java has
continuously added new features with its updates, particularly in versions
Java 5, 6, 7, and 8. These enhancements aim to improve performance,
code conciseness, and support new programming paradigms.

Key Features Mentioned:

 Functional Interface

 Lambda Expression

 For-Each Method

 Switch Expression

 Sealed Classes

 Autoboxing

 Generics

 Varargs

 Java Annotations

 Method References

 Stream API

 Try-with-Resources

 Diamond Syntax

 Local Variable Type Inference

 Yield Keyword

 Text Blocks

 Java Records
 Java Module System

 Base64 Encoding/Decoding

The main focus of this unit is on the newer additions, predominantly from
Java 8, 9, 10, 13, 14, and 15.

2. Java 8 Functional Interface

Introduced in Java 8, a Functional Interface is an interface that contains


exactly one abstract method. It can, however, have any number of
default and static methods. It can also declare methods of the Object
class.

Key Concepts:

 Single Abstract Method Interface (SAM Interface): This is


another name for a functional interface, highlighting its core
characteristic.

 Purpose: It is primarily used to achieve a functional programming


approach in Java.

 Annotation: The @FunctionalInterface annotation (e.g.,


@FunctionalInterface public interface MyInterface { ... }) is optional
but highly recommended. It restricts the interface to ensure it
remains a functional interface, throwing a compile-time error if more
than one abstract method is added.

 Predefined Functional Interfaces: Java provides several


predefined functional interfaces in the java.util.function package,
including:

 Consumer: Takes an argument but returns nothing (consumes).

 Function: Takes an argument and returns a result.

 Predicate: Takes an argument and returns a boolean value


(true/false).

 Supplier: Takes no arguments but returns a result (supplies).

 Custom Functional Interfaces: Developers can also define their


own custom functional interfaces.

Example (Valid Functional Interface):

@FunctionalInterface

interface MyInterface {

public void sayRitvik(); // Single abstract method


default void doSomething() { // Default method

System.out.println("Doing something");

static void anotherStaticMethod() { // Static method

System.out.println("Another static method");

3. Java Lambda Expression

Also introduced in Java 8, Lambda Expressions are a new and important


feature that provides a clear and concise way to represent an
interface method using an expression. They are particularly useful
with collection libraries for operations like iteration, filtering, and data
extraction.

Key Concepts:

 Anonymous Function: A lambda expression is essentially an


anonymous function – a function without a name, return type, or
access modifier.

 Implementation of Functional Interfaces: Lambda expressions


are primarily used to provide the implementation for functional
interfaces (which have only one abstract method).

 Conciseness: They significantly reduce the amount of boilerplate


code, making the code shorter and more readable.

 Benefits:Less coding (shorthand method).

 Enables functional programming.

 Makes code more readable, maintainable, and concise.

 Supports parallel processing.

 Reduces JAR file size.

 Components/Syntax: A lambda expression has three main


components:

1. Argument List: Enclosed in parentheses (). Can be empty, have


one parameter, or multiple parameters.

2. Arrow Token: -> connects the argument list to the body.

3. Body: Contains the expression or statement(s) to be executed.


Syntax Examples:

 No Parameters: () -> { System.out.println("No parameters"); }

 One Parameter: (param) -> { System.out.println(param); } or


param -> { System.out.println(param); } (parentheses optional for
single parameter)

 Multiple Parameters: (param1, param2) ->


{ System.out.println(param1 + param2); }

Example (Using Lambda Expression with Functional Interface):

@FunctionalInterface

interface Drawable {

public void draw(int width);

public class LambdaExample {

public static void main(String[] args) {

int width = 10;

// Lambda expression to implement the draw method

Drawable d = (w) -> {

System.out.println("Drawing " + w);

};

d.draw(width); // Output: Drawing 10

4. Java Method References

Method References, introduced in Java 8, provide an even more compact


and easier way to refer to methods of functional interfaces, often
serving as an alternative to lambda expressions when a lambda simply
calls an existing method.

Key Concepts:

 Concise Lambda Replacement: When a lambda expression


merely invokes an existing method, a method reference can be used
to make the code even shorter and more readable.
 Purpose: To refer to a method of a functional interface.

1. Types of Method References:Reference to a Static Method:


Refers to a static method of a class.

 Syntax: ContainingClass::staticMethodName

1. Reference to an Instance Method: Refers to an instance method


of an object.

 Syntax: containingObject::instanceMethodName

1. Reference to a Constructor: Refers to a constructor.

 Syntax: ClassName::new

Example (Reference to a Static Method):

class MyClass {

public static void myStaticMethod() {

System.out.println("Static method called.");

interface MyInterface {

void display();

public class StaticMethodRefExample {

public static void main(String[] args) {

MyInterface mi = MyClass::myStaticMethod; // Method reference

mi.display(); // Output: Static method called.

5. Stream API

The Stream API, another significant addition in Java 8, is used to process


objects from a collection in a functional style. A "stream" is a sequence
of elements that supports various operations.
Key Concepts:

 Collection vs. Stream: A collection (e.g., List, Set) holds data,


while a stream processes data from a source (like a collection or an
array).

 Converting Collection to Stream: A collection can be converted


to a stream using the .stream() method.

1. Flow of Operations:Source: (e.g., Collection, Array, I/O Channel)

2. Stream Instance Creation: collection.stream()

3. Intermediate Operations: Transform the stream into another


stream (e.g., filter, map, distinct, sorted, limit).

4. Terminal Operations: Produce a result and terminate the stream


(e.g., forEach, collect, reduce, count, max, min).

5. Result: (e.g., aggregated result, new collection)

 Immutability: Stream operations produce new streams or results


without modifying the original data source.

 Pipeline: The sequence of intermediate and terminal operations on


a stream is often referred to as a "pipeline."

 Advantages:Enhances functional programming in Java.

 Supports powerful data processing operations (filtering, sorting,


mapping).

 Enables efficient parallel processing.

 Makes code more readable and maintainable.

 Common Operations:Filter: Selects elements that satisfy a given


Predicate.

 Map: Transforms each element using a Function to produce a new


stream.

 Sorted: Sorts elements in natural order or using a custom


Comparator.

 Distinct: Returns a stream with unique elements.

 Limit: Truncates the stream to a maximum size.

 forEach: Performs an action on each element (terminal operation).

 Collect: Gathers elements into a Collection.

 Count: Returns the number of elements.


 Min/Max: Finds the minimum/maximum element.

Example (Stream Operations):

List<String> names = Arrays.asList("Ritvik", "Aryan", "Mohit", "Sourabh",


"Swapnil");

// Filtering and printing names starting with 'S'

names.stream()

.filter(name -> name.startsWith("S"))

.forEach(System.out::println);

// Output:

// Sourabh

// Swapnil

// Sorting names alphabetically

names.stream()

.sorted()

.forEach(System.out::println);

// Output:

// Aryan

// Mohit

// Ritvik

// Sourabh

// Swapnil

6. Default and Static Methods in Interfaces

Introduced in Java 8, these allow methods with implementations to be


defined inside interfaces. This helps in evolving interfaces without
breaking existing implementations.

Key Concepts:

 Default Methods:Defined inside an interface using the default


keyword.
 Provide a default implementation for methods, allowing existing
classes implementing the interface to inherit the new method
without requiring immediate modification.

 Can be overridden by implementing classes.

 "Non-abstract" methods within an interface.

 Static Methods:Defined inside an interface using the static


keyword.

 Belong to the interface itself, not to any specific instance of a class


implementing the interface.

 Cannot be overridden by implementing classes.

 Used to define utility methods related to the interface.

 Purpose: To add new functionalities to existing interfaces without


affecting classes that already implement them. This solves the
"diamond problem" related to multiple inheritance by providing a
concrete implementation.

Example:

interface MyInterface {

void abstractMethod(); // Abstract method (no implementation)

default void defaultMethod() { // Default method

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

static void staticMethod() { // Static method

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

class MyClass implements MyInterface {

@Override

public void abstractMethod() {


System.out.println("Implementing abstract method.");

public class InterfaceMethodsExample {

public static void main(String[] args) {

MyClass obj = new MyClass();

obj.abstractMethod();

obj.defaultMethod(); // Calls default method

MyInterface.staticMethod(); // Calls static method directly from interface

7. Base64 Encoding and Decoding

Java 8 introduced built-in support for Base64 encoding and decoding,


standardizing the process of converting binary data into text format
and vice-versa. This ensures data integrity during network transmission.

Key Concepts:

 Purpose: To encode binary data (0s and 1s) into a textual format
(A-Z, a-z, 0-9, +, /) that can be easily transported over networks
without corruption or data loss. Decoding reverses this process.

 Pre-Java 8: Prior to Java 8, Base64 support often relied on non-


public (and limited) classes or external libraries.

 java.util.Base64 Package: Java 8 introduced the public


java.util.Base64 class, simplifying Base64 operations.

1. Types of Encoders/Decoders:Basic Encoding/Decoding:


Standard Base64 as defined by RFC 4648 and RFC 2045. It does not
add line separators.

2. URL and Filename Safe Encoding/Decoding: A variant for URL


and filename safe Base64 encoding (replaces + with - and / with _).

3. MIME Encoding/Decoding: Adheres to RFC 2045, often used in


email. It ensures that encoded output lines are no more than 76
characters long and adds line separators.
 Methods: The Base64 class provides getEncoder() and
getDecoder() methods to obtain Base64.Encoder and
Base64.Decoder instances respectively.

Example (Basic Encoding/Decoding):

import java.util.Base64;

public class Base64Example {

public static void main(String[] args) {

String originalInput = "Hello, World!";

// Encode

String encodedString =
Base64.getEncoder().encodeToString(originalInput.getBytes());

System.out.println("Encoded: " + encodedString); // Output:


SGVsbG8sIFdvcmxkIQ==

// Decode

byte[] decodedBytes = Base64.getDecoder().decode(encodedString);

String decodedString = new String(decodedBytes);

System.out.println("Decoded: " + decodedString); // Output: Hello, World!

8. For-Each Method

The For-Each method is a utility function introduced in Java 8 that allows


iteration over collections (Lists, Sets, Maps) and streams in a more
concise way, often using lambda expressions or method references.

Key Concepts:

 Utility Function: A function that performs a common, often


reusable operation.

 Iteration: Used to perform a given action on each element of a


collection or stream.
 Applicability:Iterable Interface: Available to List, Set, and other
collections (except Map).

 Map Interface: Has its own forEach method.

 Stream Interface: Offers forEach and forEachOrdered methods.

 Parameter: Takes a single parameter, which is a functional


interface (typically a Consumer), allowing lambda expressions to be
passed as arguments.

 Benefits: Reduces the boilerplate code of traditional for loops,


making iteration more readable and functional.

Example (For-Each with List and Lambda):

import java.util.ArrayList;

import java.util.List;

public class ForEachExample {

public static void main(String[] args) {

List<String> names = new ArrayList<>();

names.add("Alice");

names.add("Bob");

names.add("Charlie");

// Using forEach with a lambda expression

names.forEach(name -> System.out.println("Hello, " + name));

// Output:

// Hello, Alice

// Hello, Bob

// Hello, Charlie

9. Try-With-Resources
Introduced in Java 7, Try-With-Resources is a statement that ensures that
each resource opened in the try block is automatically closed at
the end of the block, whether normally or abnormally.

Key Concepts:

 Problem Solved (Pre-Java 7): Before Java 7, developers had to


explicitly close resources (like InputStream, OutputStream, database
connections) in a finally block to prevent resource leaks. This
increased code complexity and length.

 Automatic Resource Management (ARM): Try-With-Resources


automates this closing process.

 AutoCloseable Interface: Any object that implements the


java.lang.AutoCloseable interface (or java.io.Closeable, which
extends AutoCloseable) can be used in a Try-With-Resources
statement.

 Syntax: Resources are declared within the parentheses after the try
keyword.

Syntax Example:

try (Resource resource1 = new Resource(); Resource resource2 = new


Resource()) {

// Use resource1 and resource2

} catch (Exception e) {

// Handle exceptions

// resource1 and resource2 are automatically closed here

Benefits:

 Reduces boilerplate code by eliminating the need for an explicit


finally block for closing resources.

 Improves code readability and conciseness.

 Prevents common resource leak bugs.

 Supports multiple resources separated by semicolons.

10. Java Annotations

Annotations are a form of metadata that can be added to Java source


code. They provide supplementary information about the program but do
not directly affect its execution. They are processed by compilers and
JVMs.

Key Concepts:

 Metadata: Data about data (e.g., details of a photo like time, date,
size). Annotations provide metadata about classes, interfaces,
methods, fields, etc.

 Introduced: JDK 5.

 Syntax: Start with @ symbol (e.g., @Override).

 Purpose:Provide information to the compiler (e.g., @Override helps


detect errors if a method is not actually overriding).

 Generate code (e.g., for frameworks like Spring or Hibernate).

 Runtime processing (can be inspected at runtime using reflection).

 Difference from Comments: Unlike comments, which are ignored


by the compiler, annotations are read and processed by the
compiler and JVM.

 Optional: They are not mandatory for code execution.

1. Types of Annotations (General):Marker Annotations: No


elements (e.g., @Override).

2. Single-Value Annotations: One element (e.g.,


@SuppressWarnings("unchecked")).

3. Full Annotations: Multiple elements (e.g., @Author(name="John


Doe", date="2023-01-01")).

 Standard Built-in Annotations:@Override: Indicates that a


method overrides a superclass method.

 @Deprecated: Marks an element as deprecated, indicating it should


no longer be used.

 @SuppressWarnings: Suppresses compiler warnings.

 Meta-Annotations (Annotations that annotate other


annotations):@Target: Specifies where an annotation can be
applied (e.g., method, class).

 @Retention: Specifies how long an annotation is retained (source,


class, runtime).

 @Inherited: Indicates that an annotation can be inherited by


subclasses.
 @Documented: Includes the annotation in Javadoc.

11. Type Annotations and Repeating Annotations

These are advanced uses of annotations, primarily introduced in Java 8.

11.1 Type Annotations:

 Introduced: Java 8.

 Purpose: Can be applied to any place where a type is used, not just
declarations. This includes:

 Return types of methods.

 Type arguments (e.g., List<@NonNull String>).

 new expressions.

 instanceof checks.

 Type casts.

 Benefit: Enables richer static analysis and allows frameworks to


validate types at various points in the code.

Example:

public class TypeAnnotationExample {

public @NonNull String getName() { // Annotation on return type

return "John Doe";

public void processList(List<@NotEmpty String> items) { // Annotation on


type argument

// ...

11.2 Repeating Annotations:

 Introduced: Java 8.

 Purpose: Allows applying the same annotation multiple times to a


single declaration.
 Mechanism: Requires a "container annotation" to hold the multiple
instances of the repeatable annotation. The repeatable annotation
itself must be annotated with @Repeatable.

Example:

import java.lang.annotation.Repeatable;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)

@Repeatable(Schedules.class)

@interface Schedule {

String day();

@Retention(RetentionPolicy.RUNTIME)

@interface Schedules {

Schedule[] value();

public class RepeatingAnnotationExample {

@Schedule(day = "Monday")

@Schedule(day = "Wednesday")

public void doWork() {

System.out.println("Working on scheduled days.");

public static void main(String[] args) {

// Can retrieve multiple Schedule annotations at runtime


Schedule[] schedules =
RepeatingAnnotationExample.class.getAnnotation(Schedules.class).value(
);

for (Schedule s : schedules) {

System.out.println("Scheduled for: " + s.day());

12. Java Module System (Project Jigsaw)

A major change introduced in Java 9, the Module System (Project Jigsaw)


restructures the JDK into a set of modules and allows developers to create
their own.

Key Concepts:

 Problem Solved (Pre-Java 9): Before Java 9, the JDK was a


monolithic structure, making applications heavy and difficult to
deploy on small devices. The entire rt.jar (runtime library) was
included, even if only a small part was needed.

 Definition: A module is a named, self-describing collection of


related packages, types (classes, interfaces), and resources.

 Purpose: To make Java more scalable, secure, and maintainable by


allowing developers to bundle only the necessary parts of the Java
platform and their application code.

 Modular JARs: Java 9 introduced modular JAR files, which include a


module-info.class file in their root folder. This file is called the
Module Descriptor.

 Module Descriptor (module-info.java):Describes the module's


name.

 Specifies which packages it exports (makes available to other


modules).

 Specifies which other modules it requires (depends on).

 Example:module com.javamodule {

 exports com.javamodule.greetings; // Exports this package

 requires java.base; // Requires the base Java module

 }
 Benefits:Reliable Configuration: Strong encapsulation ensures
that modules only expose what they intend to.

 Strong Encapsulation: Code outside a module cannot access non-


exported packages within it.

 Scalability: Allows for smaller runtime images and applications.

 Maintainability: Clear dependencies make applications easier to


understand and maintain.

 Improved Security: Reduces the attack surface by only including


necessary modules.

1. Creating a Module:Create Directory Structure: Follows a


reverse-domain pattern (e.g., com/javamodule).

2. Create Module Descriptor: module-info.java file.

3. Write Java Source Code.

4. Compile: Use javac --module-source-path <path> -d <output-dir>


<module-info-file> <java-files>.

5. Run: Use java --module-path <path> --module


<module-name>/<main-class>.

 java.base Module: The fundamental module in JDK 9+, containing


core Java APIs, and is implicitly required by all other modules.

13. Diamond Syntax Enhancement

The "Diamond Operator" (<>) was introduced in Java 7 to reduce


verbosity when creating instances of generic classes. Its
enhancement in Java 9 extended its applicability.

Key Concepts:

 Introduced: Java 7.

 Purpose: To avoid redundant type specification when instantiating


a generic class.

 Pre-Java 7: Developers had to specify the generic type arguments


on both the left and right sides of the assignment.

 List<String> list = new ArrayList<String>();

 Java 7 Improvement: The diamond operator allowed omitting the


type arguments on the right-hand side, as the compiler could infer
them.

 List<String> list = new ArrayList<>();


 Java 7 Limitation: The diamond operator could not be used with
anonymous inner classes in Java 7, leading to a compilation error.

 Java 9 Enhancement: Java 9 improved the diamond operator to


allow its use with anonymous inner classes. This further
reduces boilerplate code for such scenarios.

Example (Java 9 Diamond with Anonymous Inner Class):

import java.util.ArrayList;

import java.util.List;

public class DiamondOperatorEnhancement {

public static void main(String[] args) {

// Java 7 would throw a compilation error here for anonymous inner class

List<Integer> numbers = new ArrayList<Integer>() { // Anonymous inner


class

add(10);

add(20);

};

// In Java 9+, this is allowed:

List<Integer> numbers9 = new ArrayList<>() { // Diamond operator with


anonymous inner class

add(30);

add(40);

};

System.out.println(numbers);

System.out.println(numbers9);
}

14. Local Variable Type Inference (LVTI - var keyword)

Introduced in Java 10, Local Variable Type Inference allows developers to


skip the explicit type declaration for local variables, letting the
compiler infer the type automatically.

Key Concepts:

 Introduced: Java 10.

 Keyword: var

 Purpose: To reduce boilerplate code and improve readability by


allowing the compiler to deduce the type of local variables from
their initializers.

 Compiler's Role: The Java compiler (JDK 10+) figures out the data
type of the variable at compile time based on the value assigned to
it.

 Applicability (Use Cases):Local variables with initializers (e.g., var


name = "John";).

 Index variables in traditional for loops (e.g., for (var i = 0; i < 10; i+
+)).

 Iteration variables in enhanced for loops (e.g., for (var item : list)).

 Variables declared in try-with-resources statements.

 Restrictions (Where var cannot be used):Class fields (instance


or static variables).

 Method parameters.

 Method return types.

 Uninitialized local variables (e.g., var x;).

 Variables initialized to null (e.g., var x = null;).

 In lambda expression parameters.

 For multiple variable declarations on a single line.

Example (Using var):

import java.util.ArrayList;

import java.util.List;
public class VarKeywordExample {

public static void main(String[] args) {

// Before Java 10

String name = "Alice";

List<String> messages = new ArrayList<>();

// With 'var' (Java 10+)

var newName = "Bob"; // newName is inferred as String

var newMessages = new ArrayList<String>(); // newMessages is inferred


as ArrayList<String>

System.out.println(newName);

newMessages.add("Hello");

System.out.println(newMessages);

15. Switch Expressions

Introduced as a preview feature in Java 12, finalized in Java 14, Switch


Expressions are an enhancement to the traditional switch statement,
allowing it to return a value and offering a more concise syntax.

Key Concepts:

 Problem Solved (Traditional switch statement):Fall-through:


Requires break statements to prevent execution of subsequent
cases.

 Verbosity: Can be quite long with many cases and break


statements.

 Auxiliary Variable: Often requires a separate variable to store the


result.

 Expression vs. Statement: Unlike switch statements which


perform an action, switch expressions produce a result.
 Arrow Syntax (->): New syntax using case L -> result; which
implicitly handles break.

 Return Value: The switch expression can directly assign a value to


a variable.

 yield Keyword (Java 13/14): Used within a switch expression to


explicitly yield a value from a case block, especially when a case
block contains multiple statements.

Example (Switch Expression):

public class SwitchExpressionExample {

public static void main(String[] args) {

String day = "MONDAY";

// Traditional Switch Statement

int numLettersOld;

switch (day) {

case "MONDAY":

case "FRIDAY":

case "SUNDAY":

numLettersOld = 6;

break;

case "TUESDAY":

numLettersOld = 7;

break;

case "THURSDAY":

case "SATURDAY":

numLettersOld = 8;

break;

case "WEDNESDAY":

numLettersOld = 9;

break;
default:

numLettersOld = -1;

System.out.println("Old Switch: " + numLettersOld);

// Switch Expression (Java 14+)

int numLettersNew = switch (day) {

case "MONDAY", "FRIDAY", "SUNDAY" -> 6;

case "TUESDAY" -> 7;

case "THURSDAY", "SATURDAY" -> 8;

case "WEDNESDAY" -> 9;

default -> -1;

};

System.out.println("New Switch: " + numLettersNew);

16. Yield Keyword

Introduced as a preview feature in Java 13 and standardized in Java 14,


the yield keyword is used within switch expressions to produce a value
from a case block.

Key Concepts:

 Introduced: Java 13 (preview), Java 14 (standard).

 Purpose: To explicitly return a value from a case label within a


switch expression block, especially when a case block requires
multiple statements to compute the result. It also acts as a
terminator for the case block.

 Difference from return:return exits the entire method or


constructor.

 yield exits only the switch expression, transferring control to the


statement immediately following the switch expression.

 Context: Exclusively used within switch expressions.


Example (Yield in Switch Expression):

public class YieldKeywordExample {

public static void main(String[] args) {

String day = "SATURDAY";

String typeOfDay = switch (day) {

case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> {

System.out.println("It's a weekday!");

yield "Weekday"; // Yields value from a block

case "SATURDAY", "SUNDAY" -> {

System.out.println("It's the weekend!");

yield "Weekend"; // Yields value from a block

default -> "Invalid Day";

};

System.out.println("Type of day: " + typeOfDay);

17. Java Text Blocks

Introduced as a preview feature in Java 13, finalized in Java 15, Text


Blocks provide a convenient way to define multi-line string literals in
Java.

Key Concepts:

 Introduced: Java 13 (preview), Java 15 (standard).

 Definition: A multi-line string literal.

 Syntax: Starts with three double-quote characters (""") followed by


optional whitespace and a newline, and ends with three double-
quote characters.
 Purpose:Readability: Improves the readability of multi-line
strings, especially for code snippets in other languages (HTML, JSON,
SQL, XML).

 Avoids Escape Sequences: Eliminates the need for most escape


sequences (\n, \", \\) for newlines and quotes within the block.

 Developer Control: Gives developers control over the formatting


of the string.

 Features:Automatic handling of newlines and indentation.

 Support for concatenation with other string literals.

 Can contain almost any characters without needing to be escaped.

 Benefit: Makes it significantly easier to embed blocks of code or


text from other languages directly into Java code.

Example:

public class TextBlockExample {

public static void main(String[] args) {

// Without Text Blocks (traditional string literal)

String htmlOld = "<html>\n" +

" <body>\n" +

" <p>Hello, world!</p>\n" +

" </body>\n" +

"</html>";

System.out.println("Old HTML:\n" + htmlOld);

// With Text Blocks (Java 15+)

String htmlNew = """

<html>

<body>

<p>Hello, world!</p>

</body>

</html>

""";
System.out.println("New HTML:\n" + htmlNew);

String json = """

"name": "Alice",

"age": 30

""";

System.out.println("JSON:\n" + json);

18. Java Records

Introduced as a preview feature in Java 14, standardized in Java 16, Java


Records are a special kind of Java class designed to concisely define
immutable data carriers.

Key Concepts:

 Introduced: Java 14 (preview), Java 16 (standard).

 Purpose: To reduce the boilerplate code typically required for data


classes (constructors, getters, equals(), hashCode(), toString()
methods).

 Immutability: Record instances are inherently immutable; once


created, their state cannot be changed.

 Declaration: Declared using the record keyword.

 Automatic Generation: The Java compiler automatically


generates:

 A canonical constructor (matching the component list).

 Accessor methods (getters) for each component (e.g., brand()


instead of getBrand()).

 equals(), hashCode(), and toString() methods.

 Restrictions:Records are implicitly final and cannot be extended.

 Cannot declare instance fields other than those declared in the


header.
 Cannot be abstract.

 Benefits:Conciseness: Significantly reduces code size for data-


only classes.

 Readability: Easier to understand the purpose of a record.

 Immutability: Promotes safe data handling.

 Boilerplate Reduction: Eliminates repetitive code.

Example:

public record Vehicle(String brand, String licensePlate) {

// Records automatically generate constructor, getters, equals(),


hashCode(), toString()

// You can add compact constructor or other methods if needed

public class RecordExample {

public static void main(String[] args) {

Vehicle myVehicle = new Vehicle("Swift", "UP32AB0001");

System.out.println("Brand: " + myVehicle.brand()); // Accessor method

System.out.println("License Plate: " + myVehicle.licensePlate()); //


Accessor method

System.out.println("Vehicle Info: " + myVehicle); // Auto-generated


toString()

// Output:

// Brand: Swift

// License Plate: UP32AB0001

// Vehicle Info: Vehicle[brand=Swift, licensePlate=UP32AB0001]

19. Sealed Classes


Introduced as a preview feature in Java 15, finalized in Java 17, Sealed
Classes and Interfaces allow developers to restrict which other classes
or interfaces can extend or implement them.

Key Concepts:

 Introduced: Java 15 (preview), Java 17 (standard).

 Purpose: To provide more control over inheritance, allowing a


class/interface to specify exactly which types are permitted to be its
direct subclasses/implementations.

 Keywords:sealed: Declares a class or interface as sealed.

 permits: Specifies the allowed direct subclasses/implementations.

 Rule for Permitted Subclasses: A permitted subclass must


explicitly be declared as final, sealed, or non-sealed.

 final: Cannot be extended further.

 sealed: Can be extended, but only by its own permitted subclasses.

 non-sealed: Can be extended by any class (breaks the sealed


hierarchy at that point).

 Benefits:Enhanced Security: Provides more control over type


hierarchies.

 Domain Modeling: Useful for modeling well-defined sets of types.

 Improved Compile-time Checks: Allows the compiler to perform


exhaustive switch checks with sealed hierarchies.

 Use Cases: Often used with Pattern Matching for instanceof (an
upcoming feature not covered in detail here but mentioned as a
future enhancement).

Example:

public sealed class Shape permits Circle, Square, Triangle {

// Common behavior or abstract methods for Shape

public final class Circle extends Shape {

// Circle specific implementation

}
public non-sealed class Square extends Shape {

// Square specific implementation, can be extended by any class

public sealed class Triangle extends Shape permits EquilateralTriangle {

// Triangle specific implementation

public final class EquilateralTriangle extends Triangle {

// EquilateralTriangle specific implementation

This briefing document covers the core concepts and important details of
the new Java features discussed in the provided source. Each section aims
to capture the essence of the topic, its purpose, syntax, and benefits,
along with relevant examples.

convert_to_textConvert to source
Quiz: Short Answer Questions
Answer each question in 2-3
sentences.
1. What is a Functional Interface in Java 8?

2. Explain the primary purpose of a Lambda Expression in Java.

3. How do Method References relate to Lambda Expressions,


and what is their main advantage?

4. Describe the two main types of operations in Java Stream


API and their fundamental difference.

5. What is the core problem that Java's try-with-resources


statement aims to solve, as compared to earlier Java
versions?

6. Define Java Annotation and provide an example of its use.

7. What is the primary benefit of the Java Module System


introduced in Java 9?

8. How did the Diamond Operator enhance code in Java 7, and


what further improvement came in Java 9 regarding
Anonymous Inner Classes?

9. Explain the concept of "Type Inference" in the context of


Java's Local Variable Type Inference (LVTI).

10. What is the key advantage of using the modern Switch


Expression (Java 14) compared to the traditional Switch
Statement?

Answer Key

1. A Functional Interface in Java 8 is an interface that contains exactly


one abstract method. It can have any number of default or static
methods, but the single abstract method is its defining
characteristic, making it suitable for functional programming.

2. The primary purpose of a Lambda Expression is to provide a concise


and clear way to represent an anonymous function, especially for
implementing functional interfaces. It reduces boilerplate code by
allowing direct implementation of the interface's abstract method
without defining a full class.
3. Method References are a compact and easy way to replicate the
functionality of Lambda Expressions, particularly when a lambda
simply refers to an existing method. They provide a shorthand for
lambda expressions that perform a single method call, improving
code readability.

4. The two main types of operations in Java Stream API are


Intermediate Operations and Terminal Operations. Intermediate
operations transform one stream into another (e.g., filter, map),
while terminal operations produce a result or a side-effect and
terminate the stream (e.g., count, forEach).

5. Java's try-with-resources statement aims to solve the problem of


ensuring that resources (like file streams) are properly closed, even
if exceptions occur. Before Java 7, programmers had to explicitly
close resources in a finally block, increasing code complexity and
potential for errors if not handled correctly.

6. Java Annotation is a form of metadata that provides additional


information about a program to the compiler or JVM. It acts like a
tag, offering supplementary details about classes, interfaces,
methods, or fields without directly affecting code execution. An
example is @Override used to indicate a method overrides a
superclass method.

7. The primary benefit of the Java Module System (Java 9) is to enable


developers to create modular applications by structuring the JDK
and user code into distinct modules. This allows for smaller
application sizes by including only required modules, improving
performance, security, and maintainability.

8. The Diamond Operator (Java 7) made it easier to employ generics


by eliminating the need to explicitly mention the type on the right-
hand side of a declaration, reducing redundancy. In Java 9, this was
further enhanced to allow the use of the diamond operator with
anonymous inner classes, which was not permitted in Java 7.

9. Type Inference refers to the automatic detection of a variable's data


type, generally performed at compile time. In Local Variable Type
Inference (LVTI) introduced in Java 10, developers can use the var
keyword instead of explicitly declaring the local variable's type, and
the compiler automatically infers the type.

10. The key advantage of using the modern Switch Expression


(Java 14) is its conciseness and expressiveness compared to the
traditional Switch Statement. It allows multiple case labels with a
single result, uses an arrow (->) instead of a colon and break
statements, and can directly return a value, leading to more
readable and less error-prone code.

Essay Format Questions

1. Discuss the evolution of functional programming support in Java,


focusing on how Functional Interfaces, Lambda Expressions, and
Method References contribute to achieving a functional
programming approach. Provide examples of how these features
work together.

2. Explain the concept of Stream API in Java 8, detailing its purpose,


architecture (source, intermediate operations, terminal operations),
and key advantages for data processing. Compare and contrast at
least three intermediate and two terminal operations with
illustrative examples.

3. Analyze the advancements in resource management and code


readability brought by try-with-resources (Java 7) and Local Variable
Type Inference (Java 10). Describe the problems each feature solves
and provide clear examples of their syntax and benefits.

4. Examine the concept of "modularity" in Java, specifically focusing on


the Java Module System introduced in Java 9. Discuss its motivation,
key components (e.g., module-info.java), and the benefits it offers
for large-scale application development. Outline the steps involved
in creating a Java 9 module.

5. Compare and contrast the traditional Switch Statement with the


modern Switch Expression (Java 14), highlighting the specific
syntactic and semantic improvements of the latter. Explain how the
yield keyword enhances the functionality of Switch Expressions,
providing examples to illustrate the differences.

Glossary of Key Terms

 Functional Interface: An interface that contains exactly one


abstract method. It can have any number of default or static
methods.

 Lambda Expression: A concise way to represent an anonymous


function. It's often used to implement functional interfaces.

 Method Reference: A compact syntax for a lambda expression


that refers to an existing method.

 Stream API: A new API introduced in Java 8 to process collections


of objects in a functional style. It supports various operations like
filtering, mapping, and reducing.
 Intermediate Operations (Stream API): Operations that
transform a stream into another stream (e.g., filter(), map(),
sorted()).

 Terminal Operations (Stream API): Operations that produce a


result or a side-effect and terminate the stream (e.g., forEach(),
count(), collect()).

 try-with-resources: A statement in Java 7 that ensures resources


opened in the try block are automatically closed when the block
exits, whether normally or due to an exception.

 AutoCloseable: An interface that indicates a resource can be


automatically closed by the try-with-resources statement.

 Java Annotation: A form of metadata that provides additional


information about a program to the compiler or JVM. It starts with @.

 Type Annotation: An annotation that can be applied to any place


where a type is used (e.g., method return types, type arguments).

 Repeating Annotation: An annotation that can be applied more


than once to a single declaration or type use.

 Java Module System (Jigsaw): Introduced in Java 9, it allows


developers to break down large applications into smaller,
manageable, and self-contained units called modules.

 module-info.java: The module descriptor file that defines a


module, including its name, exported packages, and required
modules.

 Anonymous Inner Class: An inner class that is declared and


instantiated in a single expression and does not have a name.

 Diamond Operator (<>): Introduced in Java 7, it allows for type


inference when instantiating a generic class, reducing boilerplate
code.

 Local Variable Type Inference (LVTI): A feature in Java 10 that


allows the use of the var keyword to declare local variables, letting
the compiler infer the variable's type based on the initializer.

 Switch Expression: An enhancement to the switch statement


introduced in Java 14, allowing switch to be used as an expression
that yields a value, reducing verbosity.

 yield keyword: Introduced in Java 13, it is used within switch


expressions to yield a value for a case label, providing a clearer way
to return a value and terminate the switch block.
 Default Method (Interface): A method defined inside an interface
with the default keyword. It provides a default implementation for
that method, allowing new functionality to be added to interfaces
without breaking existing implementations.

 Static Method (Interface): A method defined inside an interface


with the static keyword. These methods belong to the interface itself
and are called directly on the interface name.

 Java Base64 Encoding/Decoding: A utility in Java for encoding


binary data into a text format (Base64) and decoding it back,
primarily for safe transmission over networks.

 forEach Method: A utility function used to iterate over collections


(like lists, sets, maps) and streams, performing a given action on
each element.

 Java Text Blocks: Introduced as a standard feature in Java 15, they


are multi-line string literals that avoid the need for most escape
sequences and allow for easy embedding of multi-line text (like
HTML, JSON, SQL) directly into Java code.

 Java Records: A special kind of Java class introduced in Java 16,


designed for concisely defining immutable data carriers. They
automatically generate methods like equals(), hashCode(),
toString(), and accessor methods.

 Sealed Classes: Introduced as a preview feature in Java 15 and


standardized in Java 17, they allow a class or interface to control
which other classes or interfaces can extend or implement it,
providing more control over inheritance.

 permits keyword: Used with sealed classes or interfaces to


explicitly list the direct subclasses or implementing classes that are
allowed.

 Preview Feature: A feature introduced in Java that is not yet


permanent and might change or be removed in future releases. It's
available for developers to try out and provide feedback.

 Standard Feature: A feature that has been fully integrated into


Java and is considered stable and permanent.

You might also like