JAVA NEW FEATURES Unit-3
JAVA NEW FEATURES Unit-3
Java 8 Features
• Lambda Expressions
• Functional Interfaces
• Method Reference
• Streams
• Default method
• Static method
• ForEach method
Example 3:
(n)->{ return n*n; }
public int square(int a){ Or
return n*n; (n)-> n*n;
} n-> n*n;
Functional Interfaces
An interface with exactly one abstract method is called Functional Interface.
@FunctionalInterface annotation is added so that we can mark an interface as
functional interface. It is not mandatory to use it, but it’s best practice to use it
with functional interfaces to avoid addition of extra methods accidentally.
If the interface is annotated with @FunctionalInterface annotation and we try
to have more than one abstract method, it throws compiler error. you can have
n number of default and static methods inside a functional interface.
Example:
@FunctionalInterface
Interface A { public void m1(); }
Lambda Expression with Functional Interface: The Lambda expression is used
to provide the implementation of an interface which has functional interface. It
saves a lot of code. In case of lambda expression, we don't need to define the
method again for providing the implementation. Here, we just write the
implementation code.
Example:
interface Interf{
public void add(int a, int b); }
class Test{
public static void main(String[] args){
// lambda Expression implementation
Interf i = (a,b)->System.out.println("Sum is-----"+ (a+b));
i.add(10,20); } }
Method Reference
Method reference is used to refer method of functional interface. It is compact
and easy form of lambda expression. Each time when you are using lambda
expression to just referring a method, you can replace your lambda expression
with method reference.
Types of Method References
There are following types of method references in java:
1. Reference to a static method: You can refer to static method defined in
the class. Following is the syntax and example which describe the
process of referring static method in Java.
interface Sayable{
void say(); }
public class MethodReference {
public static void saySomething(){
System.out.println("Hello, this is static method."); }
public static void main(String[] args) {
// Referring static method
Sayable sayable = MethodReference::saySomething;
// Calling interface method
sayable.say(); } }
As discussed, this encoder uses the Basic type base64 encoding scheme. Next,
we will use the encodeToString() method. It takes a byte array as input and
returns an encoded string
String BasicBase64format=
Base64.getEncoder().encodeToString(“actualString”.getBytes());
Decode Basic Base 64 format to String
To decode an encoded string, we will use Base64.Decoder returned by the
getDecoder() method. Then, we will use the decode() method of the decoder. It
will take an encoded string as input and returns the decoded string.
byte[] actualByte= Base64.getDecoder().decode(encodedString);
String actualString= new String(actualByte);
Example
import java.util.Base64;
public class Demo{
public static void main(String args[]) {
String strToEncode = "Hello World";
//encoding
byte[] bytesToEncode = strToEncode.getBytes();
String encodedStr = Base64.getEncoder().encodeToString(bytesToEncode);
System.out.println("Encoded String: " + encodedStr);
//decoding
byte[] decodedByteArr = Base64.getDecoder().decode(encodedStr);
String decodedStr = new String(decodedByteArr);
System.out.println("Decoded String: " + decodedStr);
}}
Declaring a Module:
module com.example.myapp {
requires java.logging; // Module dependency
requires com.example.util; // Another module dependency
exports com.example.myapp.api; // Exported package
}
requires: Specifies module dependencies.
exports: Makes a package accessible to other modules.
Benefits of JPMS
Explicit Dependencies: Dependencies between modules are explicitly declared,
making the module relationships clear and maintainable.
Enhanced Encapsulation: Internal implementation details can be hidden,
exposing only the necessary APIs.This reduces the risk of unintended
dependencies and enhances security.
Improved Performance: Smaller and more efficient runtime images can be
created by including only required modules.Faster startup times and reduced
memory footprint.
For example, modules like java.base (mandatory), java.sql, java.xml, etc.
Diamond Operator
Diamond operator ‘<>’ was introduced in JDK 7. The main objective of Diamond
Operator is to instantiate generic classes very easily.
Prior to Java 7, Programmer compulsory should explicitly include the Type of
generic class in the Type Parameter of the constructor.
ArrayList<String> l = new ArrayList<String>();
Whenever we are using Diamond Operator, then the compiler will consider the
type automatically based on context, Which is also known as Type inference.
We are not required to specify TypeParameter of the Constructor explicitly.
ArrayList<String> l = new ArrayList<>();
Hence the main advantage of Diamond Operator is we are not required to
speicfy the type parameter in the constructor explicitly,length of the code will
be reduced and readability will be improved.
Eg 2:
List<Map<String,Integer>> l = new ArrayList<Map<String,Integer>>();
can be writtern with Diamond operator as follows
List<Map<String,Integer>> l = new ArrayList<>();
Switch Expression
Java 12 improved the traditional switch statement and made it more useful.
Java 13 further introduced new features. Utilizes case and -> for mapping
values, eliminating the need for break statements and reducing boilerplate
code and supports multiple values per case. Before going into the details of
new features, let’s have a look at the drawbacks faced by the traditional Switch
statement.
switch (item) {
case 001 :
System.out.println("It's a laptop!");
break;
case 002 :
System.out.println("It's a desktop!");
break;
default :
System.out.println("Unknown device!");
}
The above code works by matching the corresponding case and executing the
particular code block. As long as you provide the necessary break statements, it
works fine.
But what happens if we forget any of the required break statements:
switch (itemCode) {
case 001 :
System.out.println("It's a laptop!");
// missed out break here
case 002 :
System.out.println("It's a desktop!");
}
Here, if we pass 001, the first case matches, and the code block executes. But
due to missing break, execution falls through and continues for case 002. We
get the following wrong output:
Output: It's a laptop!
It's a desktop!
Multiple values per case not supported: There may be situations where similar
processing is required for multiple case values. But the traditional switch makes
to follow the fall through behaviors.
Upgraded Switch in Java 13
Enhancements to switch statements were introduced by Java 12 and then
further modified by Java 13.
1. Supports multiple values per case: With multiple values being specified
per case, it simplifies the code structure and eliminates the need for
using fall through.
The values need to be separated by commas and break should follow the
case block.
switch (itemCode) {
case 001, 002, 003 :
System.out.println("It's an electronic gadget!");
break;
case 004, 005:
System.out.println("It's a mechanical device!");
}
2. yield is used to return a value:
A new keyword yield has been introduced. It returns values from a
switch branch only. We don’t need a break after yield as it automatically
terminates the switch expression.
int val = switch (code) {
case "x", "y" :
yield 1;
case "z", "w" :
yield 2;
};
3. Switch can be used as an expression:
The switch can now be used as an expression. This means the switch can
now return values based on our input. There is a slight change in switch
syntax to accommodate this change. A switch block needs to be
delimited by a semicolon. The yield keyword is used to return values. No
break required with the yield statement.
4. Scope: The variables declared in the traditional switch exists until the
end of the switch statement. If we want the variables to have a case level
scope, we can use {} introduced by the enhanced switch in Java 13.
5. Switch with arrows: The new arrow ⇾ syntax has been introduced for
the switch. It can be used with the switch as an expression as well as a
statement. The statements on the right side of an ⇾ are executed if an
exact case matches on the left side.
On the right side of ⇾ we can have any of the following –
• Statement / expression
• throw statement
• {} block
public class SwitchExpressionExample {
public static void main(String[] args) {
int day = 6;
String dayName = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4 -> "Thursday";
case 5 -> "Friday";
case 6 -> "Saturday";
case 7 -> "Sunday";
default -> "Invalid day";
};
System.out.println("Day " + day + " is " + day Name); }}
Text Blocks
Java 15 Text Blocks are a new kind of string literal in Java that makes it easier to
write multi-line strings. They are enclosed in triple double-quotes ("""), which
allows developers to write strings that span multiple lines without the need for
escape sequences for special characters or new lines.
Multi-line Support: Traditional string literals require concatenation of multiple
strings or the use of escape characters for new lines. Text Blocks allow for
natural and readable multi-line strings.
Improved Readability: Text Blocks make the code more readable by preserving
the structure and indentation of the text.
Automatic Formatting: The leading and trailing whitespaces are automatically
managed. Leading whitespace on each line is removed based on the minimum
indentation level across all lines.
Text Blocks in Java provide a more readable and maintainable way to handle
multi-line strings. They are particularly useful for embedding structured data
like JSON, XML, HTML, and SQL queries within Java code. This feature enhances
the developer experience by reducing the need for escape sequences and
preserving the natural format of the text.
Example:
public class TestTextBlocks {
public static void main(String[] args) {
String textBlock = """
This is a text block.
It spans multiple lines.
No need for concatenation or escape sequences.
""";
System.out.println(textBlock);
Output:
This is a text block.
It spans multiple lines.
No need for concatenation or escape sequences.
{
"name": "John",
"age": 30,
"city": "New York"
}
Records
Record classes are a feature introduced in Java 14 as a preview and became a
standard feature in Java 16. They provide a concise way to create classes that
are primarily used to store data.
Record classes reduce boilerplate code by automatically generating common
methods such as constructors, getters, equals(), hashCode(), and toString().
Record fields are implicitly final, meaning once a record instance is created, its
fields cannot be changed.
equals(), hashCode(), and toString() methods are generated automatically,
based on the record's fields.
Example
public record Person(String name, int age) {
}
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
System.out.println(person.name()); // Alice
System.out.println(person.age()); // 30
System.out.println(person); // Person[name=Alice, age=30]
}
}
The Person record is defined with two fields: name and age. The Person record
automatically includes getter methods, a constructor, and toString(), equals(),
and hashCode() methods.
Record classes in Java provide a simplified and efficient way to create data-
carrying classes. By focusing on immutability and reducing boilerplate code,
they enhance code readability and maintainability. This feature is especially
useful for modeling simple data structures and value types.
Sealed classes
Sealed classes, introduced in Java 15 as a preview feature and finalized in Java
17, enhance the language's capability for modeling restricted class hierarchies.
This feature allows you to define a class or interface that specifies which other
classes or interfaces may extend or implement it. Sealed classes help in
providing more controlled and predictable inheritance structures, making the
code easier to maintain and understand.
//declaration of the sealed class
public sealed class Subjects permits English, Science, Mathematics, Physics {
}
public final class English extends Subjects {
public double percentage;
}
public non-sealed class Science extends Subjects {
public String grade;
}
public sealed class Mathematics extends Subjects permits AppliedMathematics
{
public double percentage;
public String grade;
}