0% found this document useful (0 votes)
6 views29 pages

Oop Unit 3 Part1

The document explains Java Functional Interfaces, which are interfaces with a single abstract method, and discusses their role in functional programming. It provides examples of functional interfaces, their usage, and introduces lambda expressions and method references in Java. Additionally, it lists predefined functional interfaces available in the java.util.function package.

Uploaded by

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

Oop Unit 3 Part1

The document explains Java Functional Interfaces, which are interfaces with a single abstract method, and discusses their role in functional programming. It provides examples of functional interfaces, their usage, and introduces lambda expressions and method references in Java. Additionally, it lists predefined functional interfaces available in the java.util.function package.

Uploaded by

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

Unit-3

Java Functional Interfaces


An Interface that contains exactly one abstract method is known as functional interface. It can
have any number of default, static methods but can contain only one abstract method. It can
also declare methods of object class.

Functional Interface is also known as Single Abstract Method Interfaces or SAM Interfaces. It
is a new feature in Java, which helps to achieve functional programming approach.

Example 1

1. @FunctionalInterface
2. interface sayable{
3. void say(String msg);
4. }
5. public class FunctionalInterfaceExample implements sayable{
6. public void say(String msg){
7. System.out.println(msg);
8. }
9. public static void main(String[] args) {
10. FunctionalInterfaceExample fie = new FunctionalInterfaceExample();
11. fie.say("Hello there");
12. }
13. }
Test it Now

Output:

Hello there

A functional interface can have methods of object class. See in the following example.

Example 2

1.
2. @FunctionalInterface
3. interface sayable{
4. void say(String msg); // abstract method
5. // It can contain any number of Object class methods.
6. int hashCode();
7. String toString();
8. boolean equals(Object obj);
9. }
10. public class FunctionalInterfaceExample2 implements sayable{
11. public void say(String msg){
12. System.out.println(msg);
13. }
14. public static void main(String[] args) {
15. FunctionalInterfaceExample2 fie = new FunctionalInterfaceExample2();
16. fie.say("Hello there");
17. }
18. }

Output:

Hello there

Invalid Functional Interface

A functional interface can extends another interface only when it does not have any abstract
method.

1. interface sayable{
2. void say(String msg); // abstract method
3. }
4. @FunctionalInterface
5. interface Doable extends sayable{
6. // Invalid '@FunctionalInterface' annotation; Doable is not a functional interface
7. void doIt();
8. }

Output:

compile-time error

Example 3

In the following example, a functional interface is extending to a non-functional interface.

1. interface Doable{
2. default void doIt(){
3. System.out.println("Do it now");
4. }
5. }
6. @FunctionalInterface
7. interface Sayable extends Doable{
8. void say(String msg); // abstract method
9. }
10. public class FunctionalInterfaceExample3 implements Sayable{
11. public void say(String msg){
12. System.out.println(msg);
13. }
14. public static void main(String[] args) {
15. FunctionalInterfaceExample3 fie = new FunctionalInterfaceExample3();
16. fie.say("Hello there");
17. fie.doIt();
18. }
19. }

Output:

Hello there
Do it now

Java Predefined-Functional Interfaces


Java provides predefined functional interfaces to deal with functional programming by using
lambda and method references.

You can also define your own custom functional interface. Following is the list of functional
interface which are placed in java.util.function package.

Interface Description

BiConsumer<T,U> It represents an operation that accepts two input arguments and


returns no result.

Consumer<T> It represents an operation that accepts a single argument and


returns no result.

Function<T,R> It represents a function that accepts one argument and returns a


result.

Predicate<T> It represents a predicate (boolean-valued function) of one


argument.

BiFunction<T,U,R> It represents a function that accepts two arguments and returns a a


result.

BinaryOperator<T> It represents an operation upon two operands of the same data type.
It returns a result of the same type as the operands.

BiPredicate<T,U> It represents a predicate (boolean-valued function) of two


arguments.

BooleanSupplier It represents a supplier of boolean-valued results.

DoubleBinaryOperator It represents an operation upon two double type operands and


returns a double type value.

DoubleConsumer It represents an operation that accepts a single double type


argument and returns no result.

DoubleFunction<R> It represents a function that accepts a double type argument and


produces a result.

DoublePredicate It represents a predicate (boolean-valued function) of one double


type argument.

DoubleSupplier It represents a supplier of double type results.


DoubleToIntFunction It represents a function that accepts a double type argument and
produces an int type result.

DoubleToLongFunction It represents a function that accepts a double type argument and


produces a long type result.

DoubleUnaryOperator It represents an operation on a single double type operand that


produces a double type result.

IntBinaryOperator It represents an operation upon two int type operands and returns
an int type result.

IntConsumer It represents an operation that accepts a single integer argument


and returns no result.

IntFunction<R> It represents a function that accepts an integer argument and


returns a result.

IntPredicate It represents a predicate (boolean-valued function) of one integer


argument.

IntSupplier It represents a supplier of integer type.

IntToDoubleFunction It represents a function that accepts an integer argument and


returns a double.

IntToLongFunction It represents a function that accepts an integer argument and


returns a long.

IntUnaryOperator It represents an operation on a single integer operand that produces


an integer result.

LongBinaryOperator It represents an operation upon two long type operands and returns
a long type result.

LongConsumer It represents an operation that accepts a single long type argument


and returns no result.

LongFunction<R> It represents a function that accepts a long type argument and


returns a result.

LongPredicate It represents a predicate (boolean-valued function) of one long type


argument.

LongSupplier It represents a supplier of long type results.

LongToDoubleFunction It represents a function that accepts a long type argument and


returns a result of double type.

LongToIntFunction It represents a function that accepts a long type argument and


returns an integer result.

LongUnaryOperator It represents an operation on a single long type operand that returns


a long type result.

ObjDoubleConsumer<T> It represents an operation that accepts an object and a double


argument, and returns no result.

ObjIntConsumer<T> It represents an operation that accepts an object and an integer


argument. It does not return result.
ObjLongConsumer<T> It represents an operation that accepts an object and a long
argument, it returns no result.

Supplier<T> It represents a supplier of results.

ToDoubleBiFunction<T,U> It represents a function that accepts two arguments and produces a


double type result.

ToDoubleFunction<T> It represents a function that returns a double type result.

ToIntBiFunction<T,U> It represents a function that accepts two arguments and returns an


integer.

ToIntFunction<T> It represents a function that returns an integer.

ToLongBiFunction<T,U> It represents a function that accepts two arguments and returns a


result of long type.

ToLongFunction<T> It represents a function that returns a result of long type.

UnaryOperator<T> It represents an operation on a single operand that returnsa a result


of the same type as its operand.

Lambda Expression in Java


In Java, Lambda expressions basically express instances of functional interfaces
(An interface with a single abstract method is called a functional interface).
Lambda Expressions in Java are the same as lambda functions which are the short
block of code that accepts input as parameters and returns a resultant value.
Lambda Expressions are recently included in Java SE 8.
Functionalities of Lambda Expression in Java
Lambda Expressions implement the only abstract function and therefore
implement functional interfaces lambda expressions are added in Java 8 and
provide the below functionalities.
 Enable to treat functionality as a method argument, or code as data.
 A function that can be created without belonging to any class.
 A lambda expression can be passed around as if it was an object and executed
on demand.
Java Lambda Expression Example
Java
// Java program to demonstrate lambda expressions
// to implement a user defined functional interface.

// A sample functional interface (An interface with


// single abstract method
interface FuncInterface
{
// An abstract function
void abstractFun(int x);

// A non-abstract (or default) function


default void normalFun()
{
System.out.println("Hello");
}
}
class Test
{
public static void main(String args[])
{
// lambda expression to implement above
// functional interface. This interface
// by default implements abstractFun()
FuncInterface fobj = (int x)->System.out.println(2*x);

// This calls above lambda expression and prints 10.


fobj.abstractFun(5);
}
}

Output
10

Lambda Expression Syntax

lambda operator -> body


Lambda Expression Parameters
There are three Lambda Expression Parameters are mentioned below:
1. Zero Parameter
2. Single Parameter
3. Multiple Parameters
1. Lambda Expression with Zero parameter
() -> System.out.println("Zero parameter lambda");
2. Lambda Expression with Single parameter
(p) -> System.out.println("One parameter: " + p);
It is not mandatory to use parentheses if the type of that variable can be inferred
from the context
Java
// A Java program to demonstrate simple lambda expressions
import java.util.ArrayList;
class Test {
public static void main(String args[])
{
// Creating an ArrayList with elements
// {1, 2, 3, 4}
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);

// Using lambda expression to print all elements


// of arrL
arrL.forEach(n -> System.out.println(n));

// Using lambda expression to print even elements


// of arrL
arrL.forEach(n -> {
if (n % 2 == 0)
System.out.println(n);
});
}
}

Output
1
2
3
4
2
4

Note: that lambda expressions can only be used to implement functional interfaces.
In the above example also, the lambda expression implements Consumer Functional
Interface.
3. Lambda Expression with Multiple parameters
(p1, p2) -> System.out.println("Multiple parameters: " + p1 + ", " + p2);
A Java program to demonstrate the working of a lambda expression with two
arguments.
Java
// Java program to demonstrate working of lambda expressions
public class Test {
// operation is implemented using lambda expressions
interface FuncInter1 {
int operation(int a, int b);
}

// sayMessage() is implemented using lambda expressions


// above
interface FuncInter2 {
void sayMessage(String message);
}

// Performs FuncInter1's operation on 'a' and 'b'


private int operate(int a, int b, FuncInter1 fobj)
{
return fobj.operation(a, b);
}

public static void main(String args[])


{
// lambda expression for addition for two parameters
// data type for x and y is optional.
// This expression implements 'FuncInter1' interface
FuncInter1 add = (int x, int y) -> x + y;

// lambda expression multiplication for two


// parameters This expression also implements
// 'FuncInter1' interface
FuncInter1 multiply = (int x, int y) -> x * y;

// Creating an object of Test to call operate using


// different implementations using lambda
// Expressions
Test tobj = new Test();

// Add two numbers using lambda expression


System.out.println("Addition is "
+ tobj.operate(6, 3, add));

// Multiply two numbers using lambda expression


System.out.println("Multiplication is "
+ tobj.operate(6, 3, multiply));

// lambda expression for single parameter


// This expression implements 'FuncInter2' interface
FuncInter2 fobj = message
-> System.out.println("Hello " + message);
fobj.sayMessage("Geek");
}
}

Output
Addition is 9
Multiplication is 18
Hello Geek

Note: Lambda expressions are just like functions and they accept parameters just
like functions.
Conclusion
Some Important points intake from this article is mentioned below:
 The body of a lambda expression can contain zero, one, or more statements.
 When there is a single statement curly brackets are not mandatory and the
return type of the anonymous function is the same as that of the body
expression.
 When there is more than one statement, then these must be enclosed in curly
brackets (a code block) and the return type of the anonymous function is the
same as the type of the value returned within the code block, or void if nothing
is returned.

Java Method References

Java provides a new feature called method reference in Java 8. 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. In this tutorial, we are explaining method
reference concept in detail.

Types of Method References


There are following types of method references in java:

1. Reference to a static method.


2. Reference to an instance method.
3. Reference to a constructor.
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.

Syntax

1. ContainingClass::staticMethodName

Example 1

In the following example, we have defined a functional interface and referring a static method
to it's functional method say().

1. interface Sayable{
2. void say();
3. }
4. public class MethodReference {
5. public static void saySomething(){
6. System.out.println("Hello, this is static method.");
7. }
8. public static void main(String[] args) {
9. // Referring static method
10. Sayable sayable = MethodReference::saySomething;
11. // Calling interface method
12. sayable.say();
13. }
14. }
Test it Now

Output:

Hello, this is static method.

Example 2

In the following example, we are using predefined functional interface Runnable to refer static
method.

1. public class MethodReference2 {


2. public static void ThreadStatus(){
3. System.out.println("Thread is running...");
4. }
5. public static void main(String[] args) {
6. Thread t2=new Thread(MethodReference2::ThreadStatus);
7. t2.start();
8. }
9. }
Test it Now
Output:

Thread is running...

Example 3

You can also use predefined functional interface to refer methods. In the following example,
we are using BiFunction interface and using it's apply() method.

1. import java.util.function.BiFunction;
2. class Arithmetic{
3. public static int add(int a, int b){
4. return a+b;
5. }
6. }
7. public class MethodReference3 {
8. public static void main(String[] args) {
9. BiFunction<Integer, Integer, Integer>adder = Arithmetic::add;
10. int result = adder.apply(10, 20);
11. System.out.println(result);
12. }
13. }
Test it Now

Output:

30

Example 4

You can also override static methods by referring methods. In the following example, we have
defined and overloaded three add methods.

1. import java.util.function.BiFunction;
2. class Arithmetic{
3. public static int add(int a, int b){
4. return a+b;
5. }
6. public static float add(int a, float b){
7. return a+b;
8. }
9. public static float add(float a, float b){
10. return a+b;
11. }
12. }
13. public class MethodReference4 {
14. public static void main(String[] args) {
15. BiFunction<Integer, Integer, Integer>adder1 = Arithmetic::add;
16. BiFunction<Integer, Float, Float>adder2 = Arithmetic::add;
17. BiFunction<Float, Float, Float>adder3 = Arithmetic::add;
18. int result1 = adder1.apply(10, 20);
19. float result2 = adder2.apply(10, 20.0f);
20. float result3 = adder3.apply(10.0f, 20.0f);
21. System.out.println(result1);
22. System.out.println(result2);
23. System.out.println(result3);
24. }
25. }
Test it Now

Output:

30
30.0
30.0

2) Reference to an Instance Method


like static methods, you can refer instance methods also. In the following example, we are
describing the process of referring the instance method.

Syntax

1. containingObject::instanceMethodName

Example 1

In the following example, we are referring non-static methods. You can refer methods by class
object and anonymous object.

1. interface Sayable{
2. void say();
3. }
4. public class InstanceMethodReference {
5. public void saySomething(){
6. System.out.println("Hello, this is non-static method.");
7. }
8. public static void main(String[] args) {
9. InstanceMethodReference methodReference = new InstanceMethodReference(); // Creating obj
ect
10. // Referring non-static method using reference
11. Sayable sayable = methodReference::saySomething;
12. // Calling interface method
13. sayable.say();
14. // Referring non-static method using anonymous object
15. Sayable sayable2 = new InstanceMethodReference()::saySomething; // You can use anonymo
us object also
16. // Calling interface method
17. sayable2.say();
18. }
19. }
Test it Now

Output:

Hello, this is non-static method.


Hello, this is non-static method.

Example 2

In the following example, we are referring instance (non-static) method. Runnable interface
contains only one abstract method. So, we can use it as functional interface.

1. public class InstanceMethodReference2 {


2. public void printnMsg(){
3. System.out.println("Hello, this is instance method");
4. }
5. public static void main(String[] args) {
6. Thread t2=new Thread(new InstanceMethodReference2()::printnMsg);
7. t2.start();
8. }
9. }
Test it Now

Output:

Hello, this is instance method

Example 3

In the following example, we are using BiFunction interface. It is a predefined interface and
contains a functional method apply(). Here, we are referring add method to apply method.

1. import java.util.function.BiFunction;
2. class Arithmetic{
3. public int add(int a, int b){
4. return a+b;
5. }
6. }
7. public class InstanceMethodReference3 {
8. public static void main(String[] args) {
9. BiFunction<Integer, Integer, Integer>adder = new Arithmetic()::add;
10. int result = adder.apply(10, 20);
11. System.out.println(result);
12. }
13. }
Test it Now

Output:

30
3) Reference to a Constructor
You can refer a constructor by using the new keyword. Here, we are referring constructor
with the help of functional interface.

Syntax

1. ClassName::new

Example

1. interface Messageable{
2. Message getMessage(String msg);
3. }
4. class Message{
5. Message(String msg){
6. System.out.print(msg);
7. }
8. }
9. public class ConstructorReference {
10. public static void main(String[] args) {
11. Messageable hello = Message::new;
12. hello.getMessage("Hello");
13. }
14. }
Test it Now

Output:

Hello

Stream In Java

Introduced in Java 8, Stream API is used to process collections of objects. A stream


in Java is a sequence of objects that supports various methods which can be
pipelined to produce the desired result.
Use of Stream in Java
There uses of Stream in Java are mentioned below:
1. Stream API is a way to express and process collections of objects.
2. Enable us to perform operations like filtering, mapping,reducing and sorting.
How to Create Java Stream?
Java Stream Creation is one of the most basic steps before considering the
functionalities of the Java Stream. Below is the syntax given on how to declare
Java Stream.
Syntax
Stream<T> stream;
Here T is either a class, object, or data type depending upon the declaration.
Java Stream Features
The features of Java stream are mentioned below:
 A stream is not a data structure instead it takes input from the Collections,
Arrays or I/O channels.
 Streams don’t change the original data structure, they only provide the result
as per the pipelined methods.
 Each intermediate operation is lazily executed and returns a stream as a result,
hence various intermediate operations can be pipelined. Terminal operations
mark the end of the stream and return the result.
Different Operations On Streams
There are two types of Operations in Streams:
1. Intermediate Operations
2. Terminate Operations
Intermediate Operations

Intermediate Operations are the types of operations in which multiple methods


are chained in a row.
Characteristics of Intermediate Operations
1. Methods are chained together.
2. Intermediate operations transform a stream into another stream.
3. It enables the concept of filtering where one method filters data and passes it
to another method after processing.
Benefit of Java Stream
There are some benefits because of which we use Stream in Java as mentioned
below:
 No Storage
 Pipeline of Functions
 Laziness
 Can be infinite
 Can be parallelized
 Can be created from collections, arrays, Files Lines, Methods in Stream,
IntStream etc.
Important Intermediate Operations
There are a few Intermediate Operations mentioned below:
1. map()
The map method is used to return a stream consisting of the results of applying
the given function to the elements of this stream.
List number = Arrays.asList(2,3,4,5);
List square = number.stream().map(x->x*x).collect(Collectors.toList());
2. filter()
The filter method is used to select elements as per the Predicate passed as an
argument.
List names = Arrays.asList("Reflection","Collection","Stream");
List result = names.stream().filter(s->s.startsWith("S")).collect(Collectors.toList());
3. sorted()
The sorted method is used to sort the stream.
List names = Arrays.asList("Reflection","Collection","Stream");
List result = names.stream().sorted().collect(Collectors.toList());
Terminal Operations
Terminal Operations are the type of Operations that return the result. These
Operations are not processed further just return a final result value.
Important Terminal Operations
There are a few Terminal Operations mentioned below:
1. collect()
The collect method is used to return the result of the intermediate operations
performed on the stream.
List number = Arrays.asList(2,3,4,5,3);
Set square = number.stream().map(x->x*x).collect(Collectors.toSet());
2. forEach()
The forEach method is used to iterate through every element of the stream.
List number = Arrays.asList(2,3,4,5);
number.stream().map(x->x*x).forEach(y->System.out.println(y));
3. reduce()
The reduce method is used to reduce the elements of a stream to a single value.
The reduce method takes a BinaryOperator as a parameter.
List number = Arrays.asList(2,3,4,5);
int even = number.stream().filter(x->x%2==0).reduce(0,(ans,i)-> ans+i);
Here ans variable is assigned 0 as the initial value and i is added to it.
Note: Intermediate Operations are running based on the concept of Lazy
Evaluation, which ensures that every method returns a fixed value(Terminal
operation) before moving to the next method.
Example of Java Stream
Java

// Java program to demonstrate

// the use of stream in java

import java.util.*;

import java.util.stream.*;

class Demo {

public static void main(String args[])

// create a list of integers

List<Integer> number = Arrays.asList(2, 3, 4, 5);

// demonstration of map method

List<Integer> square
= number.stream()

.map(x -> x * x)

.collect(Collectors.toList());

// create a list of String

List<String> names = Arrays.asList(

"Reflection", "Collection", "Stream");

// demonstration of filter method

List<String> result

= names.stream()

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

.collect(Collectors.toList());

System.out.println(result);

// demonstration of sorted method

List<String> show

= names.stream()

.sorted()

.collect(Collectors.toList());

System.out.println(show);

// create a list of integers

List<Integer> numbers
= Arrays.asList(2, 3, 4, 5, 2);

// collect method returns a set

Set<Integer> squareSet

= numbers.stream()

.map(x -> x * x)

.collect(Collectors.toSet());

System.out.println(squareSet);

// demonstration of forEach method

number.stream()

.map(x -> x * x)

.forEach(y -> System.out.println(y));

// demonstration of reduce method

int even

= number.stream()

.filter(x -> x % 2 == 0)

.reduce(0, (ans, i) -> ans + i);

System.out.println(even);

Output
[4, 9, 16, 25]
[Stream]
[Collection, Reflection, Stream]
[16, 4, 9, 25]
4
9
16
25
6
Important Points/Observations of Java Stream
1. A stream consists of a source followed by zero or more intermediate methods
combined together (pipelined) and a terminal method to process the objects
obtained from the source as per the methods described.
2. Stream is used to compute elements as per the pipelined methods without
altering the original value of the object.

Default Methods In Java 8



Before Java 8, interfaces could have only abstract methods. The implementation of
these methods has to be provided in a separate class. So, if a new method is to be
added in an interface, then its implementation code has to be provided in the class
implementing the same interface. To overcome this issue, Java 8 has introduced
the concept of default methods which allow the interfaces to have methods with
implementation without affecting the classes that implement the interface.

// A simple program to Test Interface default

// methods in java

interface TestInterface

// abstract method

public void square(int a);

// default method

default void show()

System.out.println("Default Method Executed");

class TestClass implements TestInterface


{

// implementation of square abstract method

public void square(int a)

System.out.println(a*a);

public static void main(String args[])

TestClass d = new TestClass();

d.square(4);

// default method executed

d.show();

Output:
16
Default Method Executed
The default methods were introduced to provide backward compatibility so that
existing interfaces can use the lambda expressions without implementing the
methods in the implementation class. Default methods are also known
as defender methods or virtual extension methods.
Static Methods:
The interfaces can have static methods as well which is similar to static method of
classes.

// A simple Java program to TestClassnstrate static

// methods in java

interface TestInterface
{

// abstract method

public void square (int a);

// static method

static void show()

System.out.println("Static Method Executed");

class TestClass implements TestInterface

// Implementation of square abstract method

public void square (int a)

System.out.println(a*a);

public static void main(String args[])

TestClass d = new TestClass();

d.square(4);

// Static method executed

TestInterface.show();
}

Output:
16
Static Method Executed
Default Methods and Multiple Inheritance
In case both the implemented interfaces contain default methods with same
method signature, the implementing class should explicitly specify which default
method is to be used or it should override the default method.

// A simple Java program to demonstrate multiple

// inheritance through default methods.

interface TestInterface1

// default method

default void show()

System.out.println("Default TestInterface1");

interface TestInterface2

// Default method

default void show()

System.out.println("Default TestInterface2");

}
// Implementation class code

class TestClass implements TestInterface1, TestInterface2

// Overriding default show method

public void show()

// use super keyword to call the show

// method of TestInterface1 interface

TestInterface1.super.show();

// use super keyword to call the show

// method of TestInterface2 interface

TestInterface2.super.show();

public static void main(String args[])

TestClass d = new TestClass();

d.show();

Output:
Default TestInterface1
Default TestInterface2
Important Points:
1. Interfaces can have default methods with implementation in Java 8 on later.
2. Interfaces can have static methods as well, similar to static methods in classes.
3. Default methods were introduced to provide backward compatibility for old
interfaces so that they can have new methods without affecting existing code.

Static Methods
Static Methods in Interface are those methods, which are defined in the
interface with the keyword static. Unlike other methods in Interface, these static
methods contain the complete definition of the function and since the definition
is complete and the method is static, therefore these methods cannot be
overridden or changed in the implementation class.
Similar to Default Method in Interface, the static method in an interface can be
defined in the interface, but cannot be overridden in Implementation Classes. To
use a static method, Interface name should be instantiated with it, as it is a part
of the Interface only.
Below programs illustrate static methods in interfaces:
Program 1: To demonstrate use of Static method in Interface.
In this program, a simple static method is defined and declared in an interface
which is being called in the main() method of the Implementation Class
InterfaceDemo. Unlike the default method, the static method defines in Interface
hello(), cannot be overridden in implementing the class.

 Java

// Java program to demonstrate

// static method in Interface.

interface NewInterface {

// static method

static void hello()

System.out.println("Hello, New Static Method Here");

// Public and abstract method of Interface

void overrideMethod(String str);

}
// Implementation Class

public class InterfaceDemo implements NewInterface {

public static void main(String[] args)

InterfaceDemo interfaceDemo = new InterfaceDemo();

// Calling the static method of interface

NewInterface.hello();

// Calling the abstract method of interface

interfaceDemo.overrideMethod("Hello, Override Method here");

// Implementing interface method

@Override

public void overrideMethod(String str)

System.out.println(str);

Output:
Hello, New Static Method Here
Hello, Override Method here
Program 2: To demonstrate Scope of Static method.
In this program, the scope of the static method definition is within the interface
only. If same name method is implemented in the implementation class then that
method becomes a static member of that respective class.

 Java

// Java program to demonstrate scope

// of static method in Interface.

interface PrintDemo {

// Static Method

static void hello()

System.out.println("Called from Interface PrintDemo");

public class InterfaceDemo implements PrintDemo {

public static void main(String[] args)

// Call Interface method as Interface

// name is preceding with method

PrintDemo.hello();

// Call Class static method


hello();

// Class Static method is defined

static void hello()

System.out.println("Called from Class");

Output:
Called from Interface PrintDemo
Called from Class

Base64 Encoding and Decoding in Java

Base64 is a binary-to-text encoding scheme that takes raw input bytes and encodes it in a
radix-64 representation, using the characters A-Z, a-z, 0-9, and the symbols +, / and =.
Base64 encoding is used when there is a need to store or transmit binary data over a system
that only supports text data, without losing or corrupting said data.

Java 8 provides a Base64 class in the java.util package which can be used to encode strings
into Base64, and decode Base64 strings into normal strings.

Encoding data into Base64


To encode a string into Base64, first, we convert the string into a byte array. Then, we fetch
an object of the Base64.Encoder class using Base64.getEncoder(), and pass the byte array to
the encodeToString() method:
String inputString = "hello world~";

byte[] inputStringBytes = inputString.getBytes();

String base64String = Base64.getEncoder().encodeToString(inputStringBytes);

System.out.println(base64String);

// prints: aGVsbG8gd29ybGR+

We can also perform the entire conversion within a single expression, as shown below:
String inputString = "hello world~";

String base64String = Base64.getEncoder().encodeToString(inputString.getBytes());


System.out.println(base64String);

// prints: aGVsbG8gd29ybGR+

Decoding data from Base64


To decode a Base64-encoded string, we use Base64.getDecoder() to fetch an object of
the Base64.Decoder class, and pass the input string to its decode() method. This gives us
a byte array, which can be converted to a string.
String inputString = "aGVsbG8gd29ybGR+";

byte[] base64DecodedBytes = Base64.getDecoder().decode(inputString);

String decodedString = new String(base64DecodedBytes);

System.out.println(decodedString);

// prints: hello world~

Just as before, we can perform the conversion within a single expression:


String inputString = "aGVsbG8gd29ybGR+";

String decodedString = new String(Base64.getDecoder().decode(inputString));

System.out.println(decodedString);

// prints: hello world~

URL-safe Base64 encoding


Base64 strings make use of the symbols +, /. However, these characters carry special
meaning when used in the context of a filename or an URL. For example, in the context of a
filename, a string such as AB/CD implies there's a folder named AB in which there's a file
named CD. Java supports a URL/filename-safe Base64 encoding scheme, where
the + and / characters are replaced with - and _ characters to prevent such conflicts.

We can fetch the URL-safe encoder using Base64.getUrlEncoder(). Then, we can convert our
input string to Base64 using the encodeToString() method:
String inputString = "hello world~";

String base64String = Base64.getUrlEncoder().encodeToString(inputString.getBytes());

System.out.println(base64String);

// prints: aGVsbG8gd29ybGR-

Similarly, we can fetch the URL-safe decoder using Base64.getUrlDecoder() method, and we
can convert a Base64-encoded string using the decode() method like so:
String inputString = "aGVsbG8gd29ybGR-";

String decodedString = new String(Base64.getUrlDecoder().decode(inputString));

System.out.println(decodedString);

// prints: hello world~


Removing padding characters from Base64 strings
When a string is converted to Base64, the padding character = is added to make the length of
the output string divisible by 3. This behavior is to achieve technical compliance with
the Base64 specification. However, the padding is optional and even when a Base64-
encoded string does not have padding, it can be successfully decoded.

To convert a string to Base64 without padding characters, we can use


the withoutPadding() method of the Base64.Encoder class, as shown below:
String inputString = "this is a string";

String base64String = Base64.getEncoder().withoutPadding().encodeToString(inputString.getBytes());

System.out.println(base64String);

// prints: dGhpcyBpcyBhIHN0cmluZw

Had we not used the withoutPadding() option, we would have got the
string dGhpcyBpcyBhIHN0cmluZw== as the output.

There are no special steps required for decoding the Base64-encoded string without
padding. It can be decoded using the regular Base64 decoder, like so:
String inputString = "dGhpcyBpcyBhIHN0cmluZw";

String decodedString = new String(Base64.getUrlDecoder().decode(inputString));

System.out.println(decodedString);

// prints: this is a string

MIME-compliant Base64 encoding


MIME is a specification to transmit non-ASCII data to email servers. MIME encoding is
similar to Base64 encoding, however, if the Base64-encoded data has more than 76
characters, the data is split on to multiple lines, each line having a maximum of 76
characters.

To convert a string into a MIME-compliant Base64 encoding, we can fetch the MIME-
compliant encoder by using Base64.getMimeEncoder(), and then pass the input string to
the encodeToString() method:
String inputString = "The quick brown fox jumps over the lazy dog. " +

"Jackdaws love my big sphinx of quartz. " +

"Pack my box with five dozen liquor jugs.";

String base64String = Base64.getMimeEncoder().encodeToString(inputString.getBytes());

System.out.println(base64String);

The program produces the following output. Since there are 172 characters in the output, it
has been split on to 3 lines.
VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4gSmFja2Rhd3MgbG92

ZSBteSBiaWcgc3BoaW54IG9mIHF1YXJ0ei4gUGFjayBteSBib3ggd2l0aCBmaXZlIGRvemVuIGxp

cXVvciBqdWdzLg==
We can decode a MIME-compliant Base64 string by fetching the MIME-compliant decoder
with Base64.getMimeDecoder():
String inputString =
"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4gSmFja2Rhd3MgbG92\r\n" +

"ZSBteSBiaWcgc3BoaW54IG9mIHF1YXJ0ei4gUGFjayBteSBib3ggd2l0aCBmaXZlIGRvemVuIGxp\r\n" +

"cXVvciBqdWdzLg==";

String decodedString = new String(Base64.getMimeDecoder().decode(inputString));

System.out.println(decodedString);

Running the program produces the original input string:


The quick brown fox jumps over the lazy dog. Jackdaws love my big sphinx of quartz. Pack my box with five dozen liquor
jugs.

You might also like