0% found this document useful (0 votes)
35 views26 pages

OOPS Unit III-Part I

this is the notes of object oriened programming in java to
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)
35 views26 pages

OOPS Unit III-Part I

this is the notes of object oriened programming in java to
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/ 26

UNIT III

Advance Java Features

Oracle released a new version of Java as Java 8 in March 18, 2014. It was a revolutionary
release of the Java for software development platform. It includes various upgrades to the Java
programming, JVM, Tools and libraries.

Java 8 Programming Language Enhancements

Java 8 provides following features for Java Programming:

o Lambda expressions,
o Method references,
o Functional interfaces,
o Stream API,
o Default methods,
o Base64 Encode Decode,
o Static methods in interface,
o Optional class,
o Collectors class,
o ForEach() method,
o Annotations

Java Lambda Expressions

• The lambda expression was introduced first time in Java 8.


• Its main objective to increase the expressive power of the language.
• 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.

Java lambda expression is treated as a function, so compiler does not create .class file.

First we need to understand functional interfaces.

Functional Interface
• If a Java interface contains one and only one abstract method then it is termed as
functional interface. This only one method specifies the intended purpose of the
interface.
• For example, the Runnable interface from package java.lang; is a functional interface
because it constitutes only one method i.e. run().

Example: Define a Functional Interface in java


import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
// the single abstract method
double getValue();
}

• In the above example, the interface MyInterface has only one abstract method
getValue(). Hence, it is a functional interface.
• Here, we have used the annotation @FunctionalInterface. The annotation forces the
Java compiler to indicate that the interface is a functional interface.
• Hence, does not allow to have more than one abstract method. However, it is not
compulsory though.
• In Java 7, functional interfaces were considered as Single Abstract Methods
or SAM type. SAMs were commonly implemented with Anonymous (unnamed)
Classes in Java 7.
Example: Implement SAM with anonymous classes in java
public class FunctionInterfaceTest {
public static void main(String[] args) {

// anonymous class
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I just implemented the Runnable Functional Interface.");
}
}).start();
}
}
Output:

I just implemented the Runnable Functional Interface.

Here, we can pass an anonymous class to a method. This helps to write programs with fewer
codes in Java 7. However, the syntax was still difficult and a lot of extra lines of code were
required.

• Java 8 extended the power of a SAMs by going a step further. Since we know that a
functional interface has just one method, there should be no need to define the name
of that method when passing it as an argument. Lambda expression allows us to do
exactly that.

Introduction to lambda expressions


Lambda expression is, essentially, an anonymous or unnamed method. The lambda
expression does not execute on its own. Instead, it is used to implement a method defined by
a functional interface.
Why use Lambda Expression

1. To provide the implementation of Functional interface.


2. Less coding.

Java Lambda Expression Syntax

1. (argument-list) -> {body}

Java lambda expression is consisted of three components.

1) Argument-list: It can be empty or non-empty as well.

2) Arrow-token: It is used to link arguments-list and body of expression.

3) Body: It contains expressions and statements for lambda expression.

Here is how we can define lambda expression in Java.

The new operator (->) used is known as an arrow operator or a lambda operator
Suppose, we have a method like this:

double getPiValue() {
return 3.1415;
}

We can write this method using lambda expression as:

() -> 3.1415

Here, the method does not have any parameters. Hence, the left side of the operator includes
an empty parameter. The right side is the lambda body that specifies the action of the lambda
expression. In this case, it returns the value 3.1415.

Types of Lambda Body


In Java, the lambda body is of two types.

1. A body with a single expression

() -> System.out.println("Lambdas are great");

This type of lambda body is known as the expression body.

2. A body that consists of a block of code.

() -> {
double pi = 3.1415;
return pi;
};

This type of the lambda body is known as a block body. The block body allows the lambda
body to include multiple statements. These statements are enclosed inside the braces and you
have to add a semi-colon after the braces.

Note: For the block body, you can have a return statement if the body returns a value.
However, the expression body does not require a return statement.

Example : Lambda Expression


Let's write a Java program that returns the value of Pi using the lambda expression.

As mentioned earlier, a lambda expression is not executed on its own. Rather, it forms the
implementation of the abstract method defined by the functional interface.

So, we need to define a functional interface first.

import java.lang.FunctionalInterface;

// this is functional interface


@FunctionalInterface
interface MyInterface{

// abstract method
double getPiValue();
}

public class MyTestFI {

public static void main( String[] args ) {

// declare a reference to MyInterface


MyInterface ref;

// lambda expression
ref = () -> 3.1415;

System.out.println("Value of Pi = " + ref.getPiValue());


}
}
Output:

Value of Pi = 3.1415

In the above example,

• We have created a functional interface named MyInterface. It contains a single


abstract method named getPiValue()
• Inside the Main class, we have declared a reference to MyInterface. Note that we can
declare a reference of an interface but we cannot instantiate an interface. That is,

• // it will throw an error


• MyInterface ref = new myInterface();

• // it is valid
• MyInterface ref;

• We then assigned a lambda expression to the reference.

ref = () -> 3.1415;

• Finally, we call the method getPiValue() using the reference interface. When

System.out.println("Value of Pi = " + ref.getPiValue());

Java Lambda Expression Example: No Parameter

interface MyFI
{
public String say();
}
public class LambdaExpressionEx{
public static void main(String[] args) {
MyFI s=()->{
return "Hello All";
};
System.out.println(s.say());
}
}
Lambda Expressions with parameters
Till now we have created lambda expressions without any parameters. However, similar
to methods, lambda expressions can also have parameters. For example,

(n) -> (n%2)==0

Here, the variable n inside the parenthesis is a parameter passed to the lambda expression.
The lambda body takes the parameter and checks if it is even or odd.

Java Lambda Expression Example: Single Parameter

interface MyFI
{
public String say(String name);
}
public class LambdaExpressionEx{
public static void main(String[] args) {

// Lambda expression with single parameter.


MyFI s1=(name)->{
return "Hello, "+name;
};
System.out.println(s1.say("Greet"));

// You can omit function parentheses


MyFI s2= name ->{
return "Hello, "+name;
};
System.out.println(s2.say("Greet "));
}
}

Example: Using lambda expression with parameters


@FunctionalInterface
interface MyInterface {

// abstract method
String reverse(String n);
}

public class Main {

public static void main( String[] args ) {

// declare a reference to MyInterface


// assign a lambda expression to the reference
MyInterface ref = (str) -> {

String result = "";


for (int i = str.length()-1; i >= 0 ; i--)
result += str.charAt(i);
return result;
};

// call the method of the interface


System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
}

}
Output:
Lambda reversed = adbmaL

Java Lambda Expression Example: Multiple Parameters

interface Addable{
int add(int a,int b);
}

public class LambdaExpressionExample5{


public static void main(String[] args) {

// Multiple parameters in lambda expression


Addable ad1=(a,b)->(a+b);
System.out.println(ad1.add(10,20));

// Multiple parameters with data type in lambda expression


Addable ad2=(int a,int b)->(a+b);
System.out.println(ad2.add(100,200));
}
}

Output:

30
300

Lambda Expression and Stream API


The new java.util.stream package has been added to JDK8, which allows Java developers to
perform operations like search, filter, map, reduce, or manipulate collections like Lists.
For example, we have a stream of data (in our case, a List of String) where each string is a
combination of the country name and place of the country. Now, we can process this stream of
data and retrieve only the places from Nepal.
For this, we can perform bulk operations in the stream by the combination of Stream API and
Lambda expression.

Example 6: Demonstration of using lambdas with the Stream API


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

public class StreamMain {

// create an object of list using ArrayList


static List<String> places = new ArrayList<>();

// preparing our data


public static List getPlaces(){
// add places and country to the list
places.add("Nepal, Kathmandu");
places.add("Nepal, Pokhara");
places.add("India, Delhi");
places.add("USA, New York");
places.add("Africa, Nigeria");

return places;
}

public static void main( String[] args ) {

List<String> myPlaces = getPlaces();


System.out.println("Places from Nepal:");

// Filter places from Nepal


myPlaces.stream()
.filter((p) -> p.startsWith("Nepal"))
.map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));
}

}
Output:

Places from Nepal:


NEPAL, KATHMANDU
NEPAL, POKHARA

In the above example, notice the statement

myPlaces.stream()
.filter((p) -> p.startsWith("Nepal"))
.map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));

Here, we are using the methods like filter(), map() and forEach() of the Stream API. These
methods can take a lambda expression as input.
We can also define our own expressions based on the syntax we learned above. This allows
us to reduce the lines of code drastically as we saw in the above example.

Method References

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.
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

ContainingClass::staticMethodName

Example

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

interface MyFI{
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
MyFI s = MethodReference::saySomething;
// Calling interface method
s.say();
}
}

Output:

Hello, this is static method.

Example

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

public class MethodReference2 {


public static void ThreadStatus(){
System.out.println("Thread is running...");
}
public static void main(String[] args) {
Thread t2=new Thread(MethodReference2::ThreadStatus);
t2.start();
}
}

Output:

Thread is running...

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

containingObject::instanceMethodName

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

interface Sayable{
void say();
}

public class InstanceMethodReference {


public void saySomething(){
System.out.println("Hello, this is non-static method.");
}
public static void main(String[] args) {
InstanceMethodReference methodReference = new InstanceMethodReference(); // C
reating object
// Referring non-static method using reference
Sayable sayable = methodReference::saySomething;
// Calling interface method
sayable.say();
// Referring non-static method using anonymous object
Sayable sayable2 = new InstanceMethodReference()::saySomething; // You can u
se anonymous object also
// Calling interface method
sayable2.say();
}
}

Output:

Hello, this is non-static method.


Hello, this is non-static method.

Example

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.

public class InstanceMethodReference2 {


public void printnMsg(){
System.out.println("Hello, this is instance method");
}
public static void main(String[] args) {
Thread t2=new Thread(new InstanceMethodReference2()::printnMsg);
t2.start();
}
}

Output:

Hello, this is instance method

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
interface Messageable{
Message getMessage(String msg);
}
class Message{
Message(String msg){
System.out.print(msg);
}
}
public class ConstructorReference {
public static void main(String[] args) {
Messageable hello = Message::new;
hello.getMessage("Hello");
}
}

Output:

Hello

Java Default Methods

Java provides a facility to create default methods inside the interface. Methods which are
defined inside the interface and tagged with default are known as default methods. These
methods are non-abstract methods.

Interfaces
Interfaces are like a 100-percent abstract superclass. An interface is a contract.
Definition: An interface is a reference type, similar to a class, that can contain only constants,
method signatures, default methods, static methods.
➢ Using interface, we can specify what a class must do, but not how it does it.

➢ Method bodies exist only for default methods and static methods.
➢ Interfaces cannot be instantiated—they can only be implemented by classes or extended
by other interfaces.
➢ Using interfaces, Java achieves the run time polymorphism - “one interface, multiple
methods” aspect of polymorphism.
Defining an Interface
access interface name {
// constants
type final-varname = value;
//abstract methods
return-type method-name(parameter-list);
//default methods
default type method-name(parameter-list)
{
//body
}
//static methods
static type method-name(parameter-list)
{
//body
}
}

Java Default Method Example

In the following example, Sayable is a functional interface that contains a default and an
abstract method. The concept of default method is used to define a method with default
implementation. You can override default method also to provide more specific
implementation for the method.

Let's see a simple

interface Sayable{
// Default method
default void say(){
System.out.println("Hello, this is default method");
}
// Abstract method
void sayMore(String msg);
}
public class DefaultMethods implements Sayable{
public void sayMore(String msg){ // implementing abstract method
System.out.println(msg);
}
public static void main(String[] args) {
DefaultMethods dm = new DefaultMethods();
dm.say(); // calling default method
dm.sayMore("Work is worship"); // calling abstract method

}
}

Output:
Hello, this is default method
Work is worship

Static Methods inside Java 8 Interface

You can also define static methods inside the interface. Static methods are used to define utility
methods. The following example explain, how to implement static method in interface?

interface Sayable{
// default method
default void say(){
System.out.println("Hello, this is default method");
}
// Abstract method
void sayMore(String msg);
// static method
static void sayLouder(String msg){
System.out.println(msg);
}
}
public class DefaultMethods implements Sayable{
public void sayMore(String msg){ // implementing abstract method
System.out.println(msg);
}
public static void main(String[] args) {
DefaultMethods dm = new DefaultMethods();
dm.say(); // calling default method
dm.sayMore("Work is worship"); // calling abstract method
Sayable.sayLouder("Helloooo..."); // calling static method
}
}

Output:

Hello there
Work is worship
Helloooo...

Annotation Syntax
An annotation is declared using the character @ and the annotation name,
i.e. @AnnotationName. When the compiler goes through this element, it understands that this
is an annotation.

Predefined Annotations in Java


Java comes with a set of predefined annotations. The annotations available in Java Core are
explained below:
@Retention: This annotation annotates other annotations and indicates the scope of the
annotated annotations. Some possible values are:

• SOURCE — indicates that this annotation is available only in the source code and
ignored by the Compiler and JVM, and hence not available in runtime.
• CLASS — indicates that this annotation is available to the Compiler but not JVM,
and hence not available during runtime.
• RUNTIME — indicates that the annotation is available to JVM, and hence can be
used in runtime.

@Target: This annotation indicates the target elements an annotation can be applied to:

• ANNOTATION_TYPE — means that the annotation can be applied to other


annotations.
• CONSTRUCTOR — can be applied to a constructor.
• FIELD — can be applied to a field or property.
• LOCAL_VARIABLE — can be applied to a local variable.
• METHOD— can be applied to a method.
• PACKAGE— can be applied to a package declaration.
• PARAMETER — can be applied to the parameters of a method.
• TYPE — can be applied to Class, Interface, Annotation, or enum declaration.
• PACKAGE— can be applied to package declaration.
• TYPE_PARAMETER — can be applied to the type parameter declaration.
• TYPE_USE — can be applied to any type

@Documented: This annotation can be applied to other annotations. It means that the
annotated elements will be documented using the Javadoc tool.

@Inherited: By default, annotations are not inherited by subclasses. But if an annotation is


marked as @Inherited, that means when a class is annotated with that annotation, the
annotation is also inherited by subclasses. This annotation is applicable only for class. Note
that if an interface is annotated with that annotation, the annotation is not inherited by
implementing classes.

@Deprecated: Indicates that the annotated element should not be used. This annotation gets
the compiler to generate a warning message. It can be applied to methods, classes, and fields.

@SuppressWarnings: Indicates the compiler not to produce warnings for a specific reason
or reasons.

@Override: This annotation informs the compiler that the element is overriding an element
of the superclass. It is not mandatory to use when overriding elements, but it helps the
compiler to generate errors when the overriding is not done correctly, for example, if the
subclass method parameters are different than the superclass ones, or if the return type does
not match.

@SafeVarargs: Asserts that the code of the method or constructor does not perform unsafe
operations on its arguments.
Java Type Annotations

Type annotations are one more feature introduced in Java 8. Even though we had
annotations available before, now we can use them wherever we use a type. Java 8 has
included two new features repeating and type annotations in its prior annotations topic.
In early Java versions, you can apply annotations only to declarations. After releasing
of Java SE 8 , annotations can be applied to any type use. It means that annotations can
be used anywhere you use a type.
This means that we can use them on:

• a local variable definition


• constructor calls
• type casting
• generics
• throw clauses and more

Tools like IDEs can then read these annotations and show warnings or errors based on the
annotations.

• As an example, when creating a class instance using a new operator, typecasting,


when implementing an interface using an implements clause, throws a clause, etc.,
this form of annotation is called a type annotation.

• The purpose of this type of annotation is to support improved analysis of Java


programs and ensure stronger type checking. Up to the Java 8 release, Java contained
no type-checking framework, but using the type annotation, a type checking
framework can be written and used in java program.

• Java annotations are metadata (data about data) for our program source code. There are
several predefined annotations provided by the Java SE. Moreover, we can also create
custom annotations as per needs.

As an example, suppose we want a particular variable to never be assigned null throughout


our program. We can write a custom plugin NonNull to check this and annotate that
particular variable with that custom annotation i.e if you want to avoid
NullPointerException in your code, you can declare a string variable like this:

@NonNull String str; // null value is forbidden to return (for methods), pass to (for
parameters) and hold (for local variables and fields).
When the code is compiled, the compiler checks for potential problems and raised warnings
when any such code is found where the variable may be assigned a null value.

Type Annotation Syntax

In Java 8, type annotations can be written on any use of a type, such as the following:
@Encrypted String data
List<@NonNull String> strings
MyGraph = (@Immutable Graph) tmpGraph;

Following are the examples of type annotations:

@NonNull List<String>
List<@NonNull String> str
Arrays<@NonNegative Integer> sort
@Encrypted File file
@Open Connection connection
void divideInteger(int a, int b) throws @ZeroDivisor ArithmeticException
@Override annotation was introduced so that developers could document methods as
overriding a superclass method.
• The Java compiler then uses the annotations to warn the developer if the program
doesn't match their intentions. Used this way, annotations act as a form of machine-
checked documentation.

Note - Java created type annotations to support improved analysis of Java programs. It
supports way of ensuring stronger type checking.
Local Variable Definition
Let us see how to ensure that our local variable doesn’t end up as a null value:

public class TypeAnnotations {

public static void main(String[] args) {


@NotNull String userName = args[0];
}
}
We are using annotation on the local variable definition here. A compile-time annotation
processor could now read the @NotNull annotation and throw an error when the string is
null.

Constructor Call
We want to make sure that we cannot create an empty ArrayList:

public class TypeAnnotations {

public static void main(String[] args) {


List<String> request =
new @NotEmpty ArrayList<>(Arrays.stream(args).collect(
Collectors.toList()));
}
}
This is the perfect example of how to use type annotations on a constructor. Again, an
annotation processor can evaluate the annotation and check if the array list is not empty.

Using Repeating Annotations


We can add a repating annotation multiple times to the same construct:

@Notify(email = "[email protected]")
@Notify(email = "[email protected]")
public class UserNotAllowedForThisActionException
extends RuntimeException {
final String user;

public UserNotAllowedForThisActionException(String user) {


this.user = user;

}
}
We have our custom exception class that we will throw whenever a user tries to do something
that the user is not allowed. Our annotations to this class say that we want to notify two
emails when code throws this exception.

Custom Annotations
Java allows programmers to define and implement custom annotations. The syntax to define
custom annotations is:

1
public @interface CustomAnnotation { }

This creates a new annotation type called CustomAnnotation. The @interface keyword is
used to define a custom annotation.

When defining custom annotations, two mandatory attributes must be defined for the
annotation. Other attributes can be defined here, but these two are important and mandatory.
These two attributes are the Retention Policy and Target.

These two attributes are declared in the form of annotations to that custom annotation. Also,
properties to the annotations can be defined when defining the custom annotation. For example:

1
@Retention (RetentionPolicy.RUNTIME)
2
@Target (ElementType.ELEMENT)
3
public @interface CustomAnnotation {
4
public String name() default “Mr Bean”;
5
public String dateOfBirth();
6
}

In the above custom annotation, the Retention Policy is RUNTIME, that means it is available
to the JVM at runtime and the Target is ELEMENT, which means it can be annotated to any
element type.

Also, it has two properties: name with the default value Mr Bean and one dateOfBirth with
no default value.

Note that the properties declared as Method don’t have any parameter and throws clause.
Also, the return type is restricted to String, class, enums, and annotations and arrays of the
mentioned return types.

Now, we can use our custom annotation in the following way:

1
@CustomAnnotation (dateOfBirth = “1980-06-25”)
2
public class CustomAnnotatedClass {
3

4
}

Similarly, a custom annotation for methods can be created using


the @Target ( ElementType.METHOD) annotation and can be used to annotate any method.

Java Repeating Annotations

In Java 8 release, Java allows you to repeating annotations in your source code. It is helpful
when you want to reuse annotation for the same class. You can repeat an annotation anywhere
that you would use a standard annotation.

For compatibility reasons, repeating annotations are stored in a container annotation that is
automatically generated by the Java compiler. In order for the compiler to do this, two
declarations are required in your code.

1. Declare a repeatable annotation type


2. Declare the containing annotation type

1) Declare a repeatable annotation type


Declaring of repeatable annotation type must be marked with the @Repeatable meta-
annotation. In the following example, we have defined a custom @Game repeatable annotation
type.

@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}

The value of the @Repeatable meta-annotation, in parentheses, is the type of the container
annotation that the Java compiler generates to store repeating annotations. In the following
example, the containing annotation type is Games. So, repeating @Game annotations is stored
in an @Games annotation.

2) Declare the containing annotation type

Containing annotation type must have a value element with an array type. The component type
of the array type must be the repeatable annotation type. In the following example, we are
declaring Games containing annotation type:

1. @interfaceGames{
2. Game[] value();
3. }
Note - Compiler will throw a compile-time error, if you apply the same annotation to a
declaration without first declaring it as repeatable.

Java Repeating Annotations Example 1

// Importing required packages for repeating annotation


import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// Declaring repeatable annotation type
@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}
// Declaring container for repeatable annotation type
@Retention(RetentionPolicy.RUNTIME)
@interfaceGames{
Game[] value();
}
// Repeating annotation
@Game(name = "Cricket", day = "Sunday")
@Game(name = "Hockey", day = "Friday")
@Game(name = "Football", day = "Saturday")
public class RepeatingAnnotationsExample {
public static void main(String[] args) {
// Getting annotation by type into an array
Game[] game = RepeatingAnnotationsExample.class.getAnnotationsByType(Game.
class);
for (Gamegame2 : game) { // Iterating values
System.out.println(game2.name()+" on "+game2.day());
}
}
}

OUTPUT:

Cricket on Sunday
Hockey on Friday
Football on Saturday

Java Repeating Annotations Example 2

Let us imagine we have an application with fully implemented security. It has different levels
of authorization. Even though we implemented everything carefully, we want to make sure
that we log every unauthorized action. On each unauthorized action, we are sending an email
to the owner of the company and our security admin group email. Repeating annotations are
our way to go on this example.

Repeating annotations allows us to place multiple annotations on the same class.

Creating a Repeating Annotation


For the example, we are going to create a repeating annotation called @Notify:

public class RepeatingAnnotations {

@Repeatable(Notifications.class)
public @interface Notify {
String email();
}
public @interface Notifications {
Notify[] value();
}
}
We create @Notify as a regular annotation, but we add the @Repeatable (meta-)annotation to
it. Additionally, we have to create a “container” annotation Notifications that contains an
array of Notify objects. An annotation processor can now get access to all
repeating Notify annotations through the container annotation Noifications.

Please note that this is a mock annotation just for demonstration purposes. This annotation
will not send emails without an annotation processor that reads it and then sends emails.

Java Base64 Encode and Decode

Java provides a class Base64 to deal with encryption. You can encrypt and decrypt your data
by using provided methods. You need to import java.util.Base64 in your source file to use its
methods.

Base64 encoding converts the binary data into text format, which is passed through
communication channel where a user can handle text safely.

This class provides three different encoders and decoders to encrypt information at each level.
You can use these methods at the following levels.

Difference between ASCII and base64

• When you encode text in ASCII, you start with a text string and convert it to a sequence
of bytes.
• When you encode data in Base64, you start with a sequence of bytes and convert it to
a text string.

Basic Encoding and Decoding

It uses the Base64 alphabet specified by Java in RFC 4648 and RFC 2045 for encoding and
decoding operations. The encoder does not add any line separator character. The decoder
rejects data that contains characters outside the base64 alphabet.

URL and Filename Encoding and Decoding

It uses the Base64 alphabet specified by Java in RFC 4648 for encoding and decoding
operations. The encoder does not add any line separator character. The decoder rejects data that
contains characters outside the base64 alphabet.

Nested Classes of Base64


Class Description

Base64.Decoder This class implements a decoder for decoding byte data using the Base64 encoding scheme as specified
RFC 4648 and RFC 2045.

Base64.Encoder This class implements an encoder for encoding byte data using the Base64 encoding scheme as specified
in RFC 4648 and RFC 2045.

Base64 Methods

Methods Description

public static It returns a Base64.Decoder that decodes using the Basic type base64 encoding scheme.
Base64.Decoder
getDecoder()

public static It returns a Base64.Encoder that encodes using the Basic type base64 encoding scheme.
Base64.Encoder
getEncoder()

public static It returns a Base64.Decoder that decodes using the URL and Filename safe type base64 enc
Base64.Decoder scheme.
getUrlDecoder()

public static It returns a Base64.Decoder that decodes using the MIME type base64 decoding scheme.
Base64.Decoder
getMimeDecoder()

public static It Returns a Base64.Encoder that encodes using the MIME type base64 encoding scheme.
Base64.Encoder
getMimeEncoder()

public static It returns a Base64.Encoder that encodes using the MIME type base64 encoding scheme wit
Base64.Encoder specified line length and line separators.
getMimeEncoder(int
lineLength, byte[]
lineSeparator)

public static It returns a Base64.Encoder that encodes using the URL and Filename safe type base64 enco
Base64.Encoder scheme.
getUrlEncoder()

Base64.Decoder Methods
Methods Description

public byte[] decode(byte[] src) It decodes all bytes from the input byte array using the Base64 encoding scheme, writ
results into a newly-allocated output byte array. The returned byte
array is of the length of the resulting bytes.

public byte[] decode(String src) It decodes a Base64 encoded String into a newly-allocated byte array using
the Base64 encoding scheme.

public int decode(byte[] src, It decodes all bytes from the input byte array using the Base64 encoding
byte[] dst) scheme, writing the results into the given output byte array, starting at offset
0.

public ByteBuffer It decodes all bytes from the input byte buffer using the Base64 encoding
decode(ByteBuffer buffer) scheme, writing the results into a newly-allocated ByteBuffer.

public InputStream It returns an input stream for decoding Base64 encoded byte stream.
wrap(InputStream is)

Base64.Encoder Methods

Methods Description

public byte[] encode(byte[] src) It encodes all bytes from the specified byte array into a newly-allocated byte
array using the Base64 encoding scheme. The returned byte array is of the
length of the resulting bytes.

public int encode(byte[] src, byte[] It encodes all bytes from the specified byte array using the Base64 encoding
dst) scheme, writing the resulting bytes to the given output byte array,
starting at offset 0.

public String It encodes the specified byte array into a String using the Base64 encoding
encodeToString(byte[] src) scheme.

public ByteBuffer It encodes all remaining bytes from the specified byte buffer into a
encode(ByteBuffer buffer) newly-allocated ByteBuffer using the Base64 encoding scheme. Upon return,
the source buffer's position will be updated to its limit; its limit will not
have been changed. The returned output buffer's position will be zero and
its limit will be the number of resulting encoded bytes.

public OutputStream It wraps an output stream for encoding byte data using the Base64 encoding scheme
wrap(OutputStream os)

public Base64.Encoder It returns an encoder instance that encodes equivalently to this one, but without addi
withoutPadding() padding character at the end of the encoded byte data.
Java Base64 Example: Basic Encoding and Decoding

import java.util.Base64;
public class Base64BasicEncryptionExample {
public static void main(String[] args) {
// Getting encoder
Base64.Encoder encoder = Base64.getEncoder();
// Creating byte array
Byte byteArr[] = {1,2};
// encoding byte array
Byte byteArr2[] = encoder.encode(byteArr);
System.out.println("Encoded byte array: "+byteArr2);
bytebyteArr3[] = newbyte[5]; // Make sure it has enough size to store copie
d bytes
intx = encoder.encode(byteArr,byteArr3); // Returns number of bytes written
System.out.println("Encoded byte array written to another array: "+byteArr3);
System.out.println("Number of bytes written: "+x);

// Encoding string
String str = encoder.encodeToString("JavaTpoint".getBytes());
System.out.println("Encoded string: "+str);
// Getting decoder
Base64.Decoder decoder = Base64.getDecoder();
// Decoding string
String dStr = new String(decoder.decode(str));
System.out.println("Decoded string: "+dStr);
}
}

Output:

Encoded byte array: [B@6bc7c054


Encoded byte array written to another array: [B@232204a1
Number of bytes written: 4
Encoded string: SmF2YVRwb2ludA==
Decoded string: JavaTpoint

Java Base64 Example: URL Encoding and Decoding


import java.util.Base64;
publicclass Base64BasicEncryptionExample {
publicstaticvoid main(String[] args) {
// Getting encoder
Base64.Encoder encoder = Base64.getUrlEncoder();
// Encoding URL
String eStr = encoder.encodeToString("http://www.mychannel.com/java-
tutorial/".getBytes());
System.out.println("Encoded URL: "+eStr);
// Getting decoder
Base64.Decoder decoder = Base64.getUrlDecoder();
// Decoding URl
String dStr = new String(decoder.decode(eStr));
System.out.println("Decoded URL: "+dStr);
}
}

Output:

Encoded URL:
aHR0cDovL3d3dy5qYXZhdHBvaW50LmNvbS9qYXZhLXR1dG9yaWFsLw==
Decoded URL: http://www.mychannel.com.com/java-tutorial/

You might also like