Java Unit 3
Java Unit 3
eg2:
private void add(int x, int y)
{
System.out.println(x+y)
}
(int x, int y) - >{System.out.println(x+y);}
Convert to
(int x, int y) - >{System.out.println(x+y);}
Convert to
(int x, int y) - >System.out.println(x+y);
Convert to
(x, y) - >System.out.println(x+y);
3. No return keyword
Private int show(String str)
{
return str.lenth();
}
Convert to lambda expression
Convert to
(str) - > str.length();
4. If only one param remove small brackets
(str) - >str.lebgth();
Convert to
}
};
d.draw();
}
}
Output:
java -cp /tmp/Jr0t0G9g1k/LambdaExpressionExample
Drawing 10
Example 1
@FunctionalInterface
interface sayable
{
void say(String msg);
}
public class FunctionalInterfaceExample implements sayable
{
public void say(String msg)
{
System.out.println(msg);
}
public static void main(String[] args)
{
FunctionalInterfaceExample fie = new FunctionalInterfaceExample();
fie.say("Hello there");
}
}
Output:
java -cp /tmp/Za4Nfts1VV/FunctionalInterfaceExample
Hello there
Now if suppose we don’t want to write the lambda expression code. Don’t want to write the
new implementation
We want to use the method of any other class defined previously.
We are creating a class A and method name is show() and want to use the same method in
place of lambda expression then we will use method reference.
interface abc
{
void say();
}
public class A
{
public static void show()
{
System.out.println("Hello, this is static method.");
}
public static void main(String[] args)
{
// Referring static method
abc ob = A::show;
// Calling interface method
ob.say();
}
}
Output:
Hello, this is static method.
interface abc
{
void show(String msg);
}
class A
{
A(String msg)
{
System.out.print(msg);
}
}
public class B
{
public static void main(String[] args)
{
abc ob = A::new;
ob.show("Hello");
}
}
Output:
Hello
=== Code Execution Successful ===
Java 8 Stream
Java provides a new additional package in Java 8 called java.util.stream.
Collection: Single unit of object.
Stream: If we want to process the object from a collection, then we should use a stream.
Collection to stream conversion
Stream s=collection.stream();
In Stream API, there are 2 types of operations
1. Intermediate operation
Transform a stream into another stream.
Available methods are: filter, map, distinct, sorted limit etc.
2. Terminal operation
It produces the result and terminates the string.
Available methods are forEach, collect, reduce, count etc.
filter()
The filter method is used to select elements as per the Predicate passed as an argument.
Used to filter the data
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());
sorted()
The sorted method is used to sort the stream.
collect()
The collect method is used to return the result of the intermediate operations performed on the
stream.
forEach()
The forEach method is used to iterate through every element of the stream.
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.
You can use stream to iterate any number of times. Stream provides predefined methods to deal
with the logic you implement. In the following example, we are iterating, filtering and passed a
limit to fix the iteration.
import java.util.stream.*;
public class JavaStreamExample
{
public static void main(String[] args)
{
Stream.iterate(1, element->element+1)
.filter(element->element%5==0)
.limit(5)
// .map(element->element*element)
// .sorted()
.forEach(System.out::println);
}
} Output:
5
10
15
20
25
Output:
[25000.0, 28000.0, 28000.0]
Here, we are filtering data by using stream. You can see that code is optimized and maintained.
Stream provides fast execution.
import java.util.*;
import java.util.stream.Collectors;
class A
{
int id;
String name;
float price;
public A(int id, String name, float price)
{
this.id = id;
this.name = name;
this.price = price;
}
}
public class B
{
public static void main(String[] args)
{
List<A> pl = new ArrayList<A>();
//Adding Products
pl.add(new A(1,"HP Laptop",25000f));
pl.add(new A(2,"Dell Laptop",30000f));
pl.add(new A(3,"Lenevo Laptop",28000f));
pl.add(new A(4,"Sony Laptop",28000f));
pl.add(new A(5,"Apple Laptop",90000f));
List<Float> productPriceList2 =pl.stream()
.filter(p -> p.price > 30000)// filtering data
.map(p->p.price) // fetching price
.collect(Collectors.toList()); // collecting as list
System.out.println(productPriceList2);
}
}
Output:
[100000.0, 90000.0]
}
}
Output:
Hello, this is default method
Work is worship
Class Description
Base64.Decoder This class implements a decoder for decoding byte data using the Base64
encoding scheme as specified in 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 Base64.Decoder It returns a Base64.Decoder that decodes using the Basic
getDecoder() type base64 encoding scheme.
public static Base64.Encoder It returns a Base64.Encoder that encodes using the Basic
getEncoder() type base64 encoding scheme.
public static Base64.Decoder It returns a Base64.Decoder that decodes using the URL
getUrlDecoder() and Filename safe type base64 encoding scheme.
public static Base64.Decoder It returns a Base64.Decoder that decodes using the MIME
getMimeDecoder() type base64 decoding scheme.
public static Base64.Encoder It Returns a Base64.Encoder that encodes using the MIME
getMimeEncoder() type base64 encoding scheme.
Base64.Decoder Methods
Methods Description
public byte[] decode(byte[] src) It decodes all bytes from the input byte array using
the Base64 encoding scheme, writing the 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
byte[] dst) the Base64 encoding 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
decode(ByteBuffer buffer) the Base64 encoding scheme, writing the results into
a newly-allocated ByteBuffer.
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, It encodes all bytes from the specified byte array
byte[] dst) using the Base64 encoding 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
encodeToString(byte[] src) the Base64 encoding scheme.
import java.util.Base64;
public class A
{
public static void main(String[] args)
{
// Getting encoder
Base64.Encoder encoder = Base64.getUrlEncoder();
// Encoding URL
String str = encoder.encodeToString("http://www.google.com/".getBytes());
System.out.println("Encoded URL: "+str);
// Getting decoder
Base64.Decoder decoder = Base64.getUrlDecoder();
// Decoding URl
String str1 = new String(decoder.decode(str));
System.out.println("Decoded URL: "+str1);
}
}
Output:
Encoded URL: aHR0cDovL3d3dy5nb29nbGUuY29tLw==
Decoded URL: http://www.google.com/
In Java, the Try-with-resources statement is a try statement that declares one or more
resources in it. A resource is an object that must be closed once your program is done using it.
For example, a File resource or a Socket connection resource. The try-with-resources
statement ensures that each resource is closed at the end of the statement execution. If we don’t
close the resources, it may constitute a resource leak and also the program could exhaust the
resources available to it.
You can pass any object as a resource that implements java.lang.AutoCloseable, which
includes all objects which implement java.io.Closeable.
By this, now we don’t need to add an extra finally block for just passing the closing statements
of the resources. The resources will be closed as soon as the try-catch block is executed.
Exceptions:
When it comes to exceptions, there is a difference in try-catch-finally block and try-with-
resources block. If an exception is thrown in both try block and finally block, the method
returns the exception thrown in finally block.
Now, let us discuss both the possible scenarios which are demonstrated below as an example as
follows:
Until java 1.6version it is highly recommended to write finally block to close resources which
are open as a part of try block
1. Programmer is required to close resource inside the finally block. It increases the
complexity of programing.
2. We have to write the finally block compulsory and hence it increases the length of the
code
To overcome the above problem java introduced try with resource in Java 1.7 version.
The main advantage with try with resource is whatever resources we open as a part of try
block will be closed automatically once control reaches end of the try block either normally
or abnormally and hence we are not required to close explicitly so that complexity of the
programing should be reduced.
We are not required to write finally block so that length of the code will be reduced.
Java 1.6
try
use resources
catch()
handle exception
}
finally
close resources
Java 1.7
try(resources)
use resources
catch()
handle resources
Example
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
// Using try-with-resources
try(FileOutputStream ob =new FileOutputStream("C:\\Users\\MY
COMPUTER\\Desktop\\abc.txt"))
ob.write(byteArray);
catch(Exception exception)
System.out.println(exception);
Output:
Multiple resources
We can declare multiple resouirces but these resources should be saperated with semi column
try(Resourse1, Resource2, Resource3)
{
}
Resources we can use
1. All resources should be AutoClosable resources
2. A resource is said to be auto closable if and only if corresponding class implements
java.lang.AutoClosable interface.
3. All IO related resources, database resources and network related resources are already
implemented auto closable interface.
4. Auto closable interface came in version 1.7 and it contain only one method public void
close
Example with multiple resource
/ Java program for try-with-resources
// having multiple resources
// Class
class GFG {
// Adding resource
The @Target annotation in Java is part of the java.lang.annotation package. This annotation is
used to specify the kinds of program elements to which an annotation type is applicable.
Syntax:
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
Example
// Java Program to Demonstrate Type Annotation
// Main class
public class A
{
// Annotating return type of a function
static @demo int abc() {
System.out.println("This function's return type is annotated");
return 0;
}
// Main driver method
public static void main(String[] args) {
Output:
I am annotated with a type annotation
This function's return type is annotated
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.
@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.
@interfaceGames{
Game[] value();
}
Step 1: Define the Annotation - First, define the repeatable annotation and its container.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
Step 2: Use the Repeating Annotation - Now you can use the @Schedule annotation multiple
times on the same element.
public class A {
Java 9 Module
Java added this feature to collect java packages and codes into a single unit called module.
Module is a collection of Java programs or software. To describe a module, a Java file module-
info.java is required. This file also known as module descriptor and defines the following
o Module name
o What does it export
o What does it require
Module Name
It is a name of module and should follow the reverse-domain-pattern. Like we name packages,
e.g. com.Package
Create a file module-info.java, inside this file, declare a module by using module identifier
and provide module name same as the directory name that contains it.
In our case, our directory name is com.javamodule
This is module descriptor file (empty module)
module com.javamodule
{
}
Leave module body empty, if it does not has any module dependency. Save this file
inside Java 9 space/com.javatpoint with module-info.java name.
Run Module
To run the compiled module, use the following command.
java --module-path mods/ --module com.javamodule/com.javamodule.Greeting
Output:
Welcome to the Jungle
Anonymous Class
class A
System.out.println("Class A");
}
class B extends A
System.out.println("Class B");
public class C
A ob=new B();
ob.show();
Output:
Class B
class A
{
System.out.println("Class A");
public class C
A ob=new A()
System.out.println("Class B");
};
ob.show();
Output:
Class B
Diamond Operator
Java 9 introduced a new feature that allows us to use diamond operator with anonymous classes.
Using the diamond with anonymous classes was not allowed in Java 7.
In Java 9, as long as the inferred type is denotable, we can use the diamond operator when we
create an anonymous inner class.
In Java, the diamond syntax (<>) is used to simplify the instantiation of generic classes by
allowing the compiler to infer the type parameters. When using inner anonymous classes, you
can still take advantage of the diamond syntax.
With the help of Diamond operator, we can create an object without mentioning the generic type
on the right hand side of the expression.
return a + b;
Example:
public class A
{
// diamond operator is empty, compiler infer type
return a+b;
};
System.out.println(result);
Output:
Java 9
In Java, the method declaration abstract T show(T a, T b); has the following components:
1. abstract : This keyword indicates that the method is abstract and does not have a body. It
must be implemented by any concrete subclass of the class that contains this method.
2. T: This represents a generic type parameter. The method is part of a generic class or
interface, and T is a placeholder for the actual type that will be specified when the class
or interface is instantiated.
3. show : This is the name of the method.
4. (T a, T b): These are the parameters of the method. Both a and b are of type T.
Type inference refers to the automatic detection of the datatype of a variable, done generally at
the compiler time.
Local variable type inference is a feature in Java 10 that allows the developer to skip the type
declaration associated with local and the type is inferred by the JDK. It will, then, be the job of
the compiler to figure out the datatype of the variable.
Till Java 9, to define a local variables of class type, the following was the only correct syntax:
Class_name variable_name=new Class_name(arguments);
Type Inference – Java compiler infers the type for you instead of us writing the type.
public class A
Can be written as
public class A
var age=12;
100% compile feature with no side effect in terms of bytecode, runtime or performance.
Instead of mentioning the variable datatype on the left-side, before the variable, LVTI
allows you to simply put the keyword ‘var’. For example,
// Java code for Normal local
// variable declaration
import java.util.ArrayList;
import java.util.List;
class A {
import java.util.ArrayList;
import java.util.List;
class A {
Use Cases
Here are the cases where you can declare variables using LVTI:
class A {
static
System.out.println(x)'
Output: Oh hi there
Use Cases
class A {
static
System.out.println(x)'
}
Output:
Oh hi there
2. As a local variable
class A {
System.out.println(x)
}}
Output: Hi there
class A {
public static void main(String a[])
arr = { 1, 2, 3 };
System.out.println(x + "\n");
Output:
1
2
3
class A {
arr = { 1, 2, 3 };
Output:
1
2
3
class A {
int ret()
{ return 1;
System.out.println(x);
Output:
1
class A {
int ret()
var x = 1;
return x;
System.out.println(new A().ret());
Output:
1
Switch Expressions
An easy way to differentiate between switch expressions and switch statements is that switch
expressions cannot have break in them, and switch statements cannot have yield in them.
Like all expressions, switch expressions evaluate to a single value and can be used in statements.
They may contain "case L ->" labels that eliminate the need for break statements to prevent fall
through.
You can use a yield statement to specify the value of a switch expression.
"case L ->" Labels
Consider the following switch statement that prints the number of letters of a day of the week:
// ...
int numLetters = 0;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
break;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new IllegalStateException("Invalid day: " + day);
System.out.println(numLetters);
It would be better if you could "return" the length of the day's name instead of storing it in the
variable numLetters; you can do this with a switch expression. Furthermore, it would be better
if you didn't need break statements to prevent fall through; they are laborious to write and easy
to forget. You can do this with a new kind of case label. The following is a switch expression
that uses the new kind of case label to print the number of letters of a day of the week:
System.out.println(
switch (day) {
);
The yield keyword lets us exit a switch expression by returning a value that becomes the value
of the switch expression.
To start, let’s say we have the following enum and switch statement:
public enum Number {
String message;
switch (number) {
case ONE:
break;
case TWO:
break;
default:
Let’s convert this to a switch expression and use the yield keyword along with the arrow operator:
default -> {
};
case ONE:
case TWO:
default:
};
Example text""";
In this article, we are going to discuss the Java 15 text blocks feature to declare multi-line strings
most efficiently.
We all know that how we can declare multi-line strings and that too quite easily with the help of
concatenation, string’s join method, StringBuilder append method, etc.
In earlier releases of the JDK, embedding multi-line code snippets required a tangled mess of
explicit line terminators, string concatenations, and delimiters.
Text blocks eliminate most of these obstructions, allowing you to embed code snippets and text
sequences more or less as-is.
A text block is an alternative form of Java string representation that can be used anywhere a
traditional double-quoted string literal can be used. Text blocks begin with a “”” (3 double-quote
marks) followed by optional whitespaces and a newline.
For example:
Text blocks may be utilized in the region of a string literal to enhance the clarity and readability
of the code.
This typically takes place whilst a string literal is used to symbolize a multi-line string.
In this example there’s a substantial muddle from citation marks, newline escapes, and
concatenation operators:
// ORIGINAL
"Sector-136, Noida,\n" +
Sector-136, Noida,
In Java, a record is a special type of class declaration aimed at reducing the boilerplate code.
Java records were introduced with the intention to be used as a fast way to create data carrier
classes, i.e. the classes whose objective is to simply contain data and carry it between modules,
also known as POJOs (Plain Old Java Objects) and DTOs (Data Transfer Objects).
Record was introduced in Java SE 14 as a preview feature, which is a feature whose design,
implementation, and specification are complete but it is not a permanent addition to the language,
which means that the feature may or may not exist in the future versions of the language.
Java SE 15 extends the preview feature with additional capabilities such as local record classes.
Why Record
Consider a simple class Employee, whose objective is to contain an employee’s data such as its
ID and name and act as a data carrier to be transferred across modules.
To create such a simple class, you’d need to define its constructor, getter, and setter methods,
and if you want to use the object with data structures like HashMap or print the contents of its
objects as a string, we would need to override methods such as equals(), hashCode(), and
toString().
// Records
class Employee {
{
// This keyword refers to current instance itself
this.firstName = firstName;
this.lastName = lastName;
this.Id = Id;
// Setter-getter Method 1
this.firstName = firstName;
// Setter-getter Method 2
// Setter-getter Method 3
this.lastName = lastName;
// Setter-getter Method 3
// Setter-getter Method 5
// Setter-getter Method 6
// Method 7
// Final variable
int result = 1;
return result;
// Method 8
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
if (Id != other.Id)
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
else if (!lastName.equals(other.lastName))
return false;
return true;
Step 1: Create a new Java project and select JavaSE-14 as the execution environment.
Step 2: If this is your first time using JDK-14 then there will be some more steps that you’ll need
to follow in order to configure for records to work. You might see this type of exception mark
on your project folder.
Step 3: To fix that, on the top, go to Window -> Preferences.
Step 4: In the Preferences window, click on Installed JREs and then click on Add as shown
below:
Step 5: Now on the Add JRE window that opens, select Standard VM and click Next. You’ll see
a new window open to select a JRE, now click on Directory and navigate to where your jdk-14
is installed and select that folder. Click on Finish.
Step 6: Checkmark the JDK-14 that you just added and Apply it.
Step 7: We are not done yet. Since records are a preview feature, we need to enable them to use
it. On your Project Explorer window on the left side, select your project and right-click and go
to its Properties.
Step 8: On the window that opens, to the right of it, from the various options select Java
Compiler. After that on the left side, uncheck the settings marked with red arrows in the image,
and check mark the setting highlighted with green. Doing that will enable the preview features.
Step 9: After clicking on Apply and Close, you’ll see a prompt asking whether you want to
rebuild the project. Select Yes.
Java 15 introduced the concept of sealed classes. It is a preview feature. Java sealed classes and
interfaces restrict that which classes and interfaces may extend or implement them.
In other words, we can say that the class that cannot be inherited but can be instantiated is known
as the sealed class
o It allows permission to the subclasses that can extend the sealed superclass.
o It makes superclass broadly accessible but not broadly extensible.
o It allows compilers to enforce the type system on the users of the class.
o Developer of a superclass gets control over the subclasses. Hence, they can define
methods in a more restricted way.
The declaration of a sealed class is not much complicated. If we want to declare a class as sealed,
add a sealed modifier to its declaration. After the class declaration and extends and implements
clause, add permits clause. The clause denotes the classes that may extend the sealed class.
For example, the following declaration of Subjects class specifies four permitted subclasses,
English, Science, Mathematics, and Physics.
Subjects.java
Let's define the four permitted subclasses, English, Science, Mathematics, and Physics, in the
same module or package in which the sealed class is defined.
English.java
Science.java
Mathematics.java
AppliedMathematics.java
Physics.java
On the other hand, we can also define permitted subclasses in the same file as the sealed class.
In such a case, we can omit the permits clause: