Unit IV Final
Unit IV Final
Annotations- Annotation Basics, Specifying a Retention Policy, the Annotated Element Interface,
Using Default Values, Marker Annotations, Single – Member Annotations.
Modules: Module Basics- module, exports, require, transitive, java.base and the Platform Modules,
Unnamed Module, Specific Module.
Multithreading
Fundamentals
To redude idle time of processor and improves performance of the system is the main
purpose of “Multitasking”.
Multithreading is the phenomenon of executing more than one thread(or) Operation
in the system, where the execution of these threads can be of two different types,
such as Concurrent and Parallel multithread executions.
A Thread can be defined as a chunk or unit of process, that can be identified as either
a user-level thread or a Kernel-level thread. It is usually used for its essential
characteristics like it uses the system resources efficiently, high performance, greatly
responsive, and also its parallel execution ability.
Multithreading in Java is a process of executing multiple threads simultaneously.
A thread is a lightweight sub-process, the smallest unit of processing.
Multiprocessing and multithreading, both are used to achieve multitasking.
However, we use multithreading than multiprocessing because threads use a shared
memory area. They don't allocate separate memory area so saves memory, and
context-switching between the threads takes less time than process.
Java Multithreading is mostly used in games, animation, etc.
1) It doesn't block the user because threads are independent and you can perform multiple
operations at the same time.
Multitasking
Understanding Multithreading
There are two terms that need to be understood :
In Java, a thread always exists in any one of the following states. These states are:
1. New
2. Active
3. Blocked / Waiting
4. Timed Waiting
5. Terminated
Follow ing are the stages of the life cycle –
New: Whenever a new thread is created, it is always in the new state. For a thread in
the new state, the code has not been run yet and thus has not begun its execution.
Active: When a thread invokes the start() method, it moves from the new state to the
active state. The active state contains two states within it: one is runnable, and the
other is running.
o Runnable: A thread, that is ready to run is then moved to the runnable state.
In the runnable state, the thread may be running or may be ready to run at
any given instant of time. It is the duty of the thread scheduler to provide the
thread time to run, i.e., moving the thread the running state.
A program implementing multithreading acquires a fixed slice of time to each
individual thread. Each and every thread runs for a short span of time and
when that allocated time slice is over, the thread voluntarily gives up the CPU
to the other thread, so that the other threads can also run for their slice of
time. Whenever such a scenario occurs, all those threads that are willing to
run, waiting for their turn to run, lie in the runnable state. In the runnable
state, there is a queue where the threads lie.
o Running: When the thread gets the CPU, it moves from the runnable to the
running state. Generally, the most common change in the state of a thread is
from runnable to running and again back to runnable.
For example, a thread (let's say its name is A) may want to print some data from the
printer. However, at the same time, the other thread (let's say its name is B) is using
the printer to print some data. Therefore, thread A has to wait for thread B to use the
printer. Thus, thread A is in the blocked state. A thread in the blocked state is unable
to perform any execution and thus never consume any cycle of the Central
Processing Unit (CPU). Hence, we can say that thread A remains idle until the thread
scheduler reactivates thread A, which is in the waiting or blocked state.
When the main thread invokes the join() method then, it is said that the main thread
is in the waiting state. The main thread then waits for the child threads to complete
their tasks. When the child threads complete their job, a notification is sent to the
main thread, which again moves the thread from waiting to the active state.
If there are a lot of threads in the waiting or blocked state, then it is the duty of the
thread scheduler to determine which thread to choose and which one to reject, and
the chosen thread is then given the opportunity to run.
Timed Waiting: Sometimes, waiting for leads to starvation. For example, a thread (its
name is A) has entered the critical section of a code and is not willing to leave that
critical section. In such a scenario, another thread (its name is B) has to wait forever,
which leads to starvation. To avoid such scenario, a timed waiting state is given to
thread B. Thus, thread lies in the waiting state for a specific span of time, and not
forever. A real example of timed waiting is when we invoke the sleep() method on a
specific thread. The sleep() method puts the thread in the timed wait state. After the
time runs out, the thread wakes up and start its execution from when it has left
earlier.
o When a thread has finished its job, then it exists or terminates normally.
o Abnormal termination: It occurs when some unusual events such as an
unhandled exception or segmentation fault.
A terminated thread means the thread is no more in the system. In other words, the
thread is dead, and there is no way one can respawn (active after kill) the dead
thread.
Example:
try {
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
// Main Class
object.start();
Output
Thread 15 is running
Thread 14 is running
Thread 16 is running
Thread 12 is running
Thread 11 is running
Thread 13 is running
Thread 18 is running
Thread 17 is running
try {
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
// Main Class
class Multithread {
public static void main(String[] args)
object.start();
Output
Thread 13 is running
Thread 11 is running
Thread 12 is running
Thread 15 is running
Thread 14 is running
Thread 18 is running
Thread 17 is running
Thread 16 is running
Thread Class vs Runnable Interface
1. If we extend the Thread class, our class cannot extend any other class because Java
doesn’t support multiple inheritance. But, if we implement the Runnable interface, our
class can still extend other base classes.
2. We can achieve basic functionality of a thread by extending Thread class because it
provides some inbuilt methods like yield(), interrupt() etc. that are not available in
Runnable interface.
3. Using runnable will give you an object that can be shared amongst multiple threads.
3) static void sleep() It sleeps a thread for the specified amount of time.
12) static void yield() It causes the currently executing thread object to
pause and allow other threads to execute
temporarily.
16) void destroy() It is used to destroy the thread group and all of its
subgroups.
20) boolean isinterrupted() It tests whether the thread has been interrupted.
21) static interrupted() It tests whether the current thread has been
boolean interrupted.
22) static int activeCount() It returns the number of active threads in the
current thread's thread group.
24) static holdLock() It returns true if and only if the current thread holds
boolean the monitor lock on the specified object.
25) static void dumpStack() It is used to print a stack trace of the current thread
to the standard error stream.
27) static int enumerate() It is used to copy every active thread's thread group
and its subgroup into the specified array.
31) void notify() It is used to give the notification for only one
thread which is waiting for a particular object.
33) void setContextClass It sets the context ClassLoader for the Thread.
Loader()
34) ClassLoader getContextClass It returns the context ClassLoader for the thread.
Loader()
35) static getDefaultUnca It returns the default handler invoked when a thread
Thread.Unca ughtExceptionH abruptly terminates due to an uncaught exception.
ughtExceptio andler()
nHandler
36) static void setDefaultUnca It sets the default handler invoked when a thread
ughtExceptionH abruptly terminates due to an uncaught exception.
andler()
In a java programming language, every thread has a property called priority. Most of the
scheduling algorithms use the thread priority to schedule the execution sequence. In java, the
thread priority range from 1 to 10. Priority 1 is considered as the lowest priority, and priority
10 is considered as the highest priority. The thread with more priority allocates the processor
first.
The java programming language Thread class provides two methods setPriority(int),
and getPriority( ) to handle thread priorities.
The Thread class also contains three constants that are used to set the thread priority, and they
are listed below.
setPriority( ) method
The setPriority( ) method of Thread class used to set the priority of a thread. It takes
an integer range from 1 to 10 as an argument and returns nothing (void).
The regular use of the setPriority( ) method is as follows.
Example
threadObject.setPriority(4);
or
threadObject.setPriority(MAX_PRIORITY);
getPriority( ) method
The getPriority( ) method of Thread class used to access the priority of a thread. It does not
takes anyargument and returns name of the thread as String.
The regular use of the getPriority( ) method is as follows.
Example
threadObject1.setPriority(4);
threadObject2.setPriority(Thread.MAX_PRIORITY);
threadObject1.start();
threadObject2.start();
}
}
Note:In java, it is not guaranteed that threads execute according to their priority because it
depends on JVM specification that which scheduling it chooses.
T1.start();
T2.start();
}
}
This produces a different result every time you run this program −
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 5
Counter --- 2
Counter --- 1
Counter --- 4
Thread Thread - 1 exiting.
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Example
class PrintDemo
{
public void printCount()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
T1.start();
T2.start();
T1.run();
T2.run();
}
}
This produces the same result every time you run this program −
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
o wait()
o notify()
o notifyAll()
1) wait() method
o Causes current thread to release the lock and wait until either
another thread invokes the notify() method or the notifyAll()
method for this object, or a specified amount of time has elapsed.
o The current thread must own this object's monitor, so it must be
called from the synchronized method only otherwise it will throw
exception.
Method Description
public final void wait(long timeout)throws waits for the specified amount of
InterruptedException time.
2) notify() method
Wakes up a single thread that is waiting on this object's monitor. If any threads
are waiting on this object, one of them is chosen to be awakened. The choice is
arbitrary and occurs at the discretion of the implementation. Syntax:
3) notifyAll() method
Wakes up all threads that are waiting on this object's monitor. Syntax:
class Customer
{
int amount=10000;
synchronized void withdraw(int amount)
{
System.out.println("going to withdraw...");
if(this.amount<amount)
{
System.out.println("Less balance; waiting for deposit...");
try{wait();}catch(Exception e){}
}
this.amount-=amount;
System.out.println("withdraw completed...");
}
class Test
{
public static void main(String args[])
{
Customer c=new Customer();
new Thread()
{
public void run()
{
c.withdraw(15000);
}
}.start();
new Thread()
{
public void run()
{
c.deposit(10000);
}
}.start();
}}
going to deposit...
deposit completed...
withdraw completed
In Multiprocessing, CPUs are added for created of a single process for increasing
Introduction:
As per the application requirement, if we want to bring metadata upto .java file,
upto .class file and upto RUNTIME of our application then we have to use
"Annotations".
Are different from comments since they can affect how the program is
treated by the compiler.
Hierarchy of Annotations in Java
Types of Annotation
1. Marker Annotation
2. Single-Value Annotation
3. Multi-Value Annotation
@interface Annotation_Name
{
Example:
@interface Course
2.Utilization Syntax:
Syntax:
@AnnotationName(member1=value1,member2=value2,…..,member=valuen)
Description:
Annotations are created by using @ sign, followed by the keyword interface, and
followed by annotation name as shown in the above example.
Members can be decleared as shown in the example, it looks like methods. The
example defines two members called name and desc. We should not provide
implementation for these members.
All annotations extends java.lang.annotation.Annotation interface. Annotations
cannot include any extends caluse.
Below example shows how to use this annotation to method.
Example:
//Declaration of Annotation
public @interface MySampleAnn {
String name();
String desc();
}
class MyAnnTest{
//Utilization of Annotation
@MySampleAnn(name = "test1", desc = "testing annotations")
public void myTestMethod(){
//method implementation
}
}
Description:
A retention policy determines to specify how long annotations ate to be
retained.
Java defined 3 types of retention policies through
java.lang.annotation.RetentionPolicy enumeration.
They are
(i) SOURCE
(ii) CLASS
(iii) RUNTIME.
Annotation with retention policy SOURCE will be retained only with source
code, and discarded during compile time.
Annotation with retention policy CLASS will be retained till compiling the
code, and discarded during runtime.
Annotation with retention policy RUNTIME will be available to the JVM
through runtime.
The retention policy will be specified by using java built-in annotation
@Retention, and we have to pass the retention policy type.
The default retention policy type is CLASS.
Example:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MySampleAnn {
String name();
String desc();
}
class MyAnnTest{
Description:
In case if any annotation is specifies its retention policy as RUNTIME, then
those annotations can be queried at runtime by any java program.
Below example code shows how to query an annotation values during runtime
using java reflection.
Example:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String key();
String value();
}
@MyAnnotation(key="site", value="java2novice.com")
public void myAnnotationTestMethod(){
try {
Class<? extends MyAnnotationTest> cls = this.getClass();
Method mth = cls.getMethod("myAnnotationTestMethod");
MyAnnotation myAnno = mth.getAnnotation(MyAnnotation.class);
System.out.println("key: "+myAnno.key());
System.out.println("value: "+myAnno.value());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Description:
In case if any annotation is specifies its retention policy as RUNTIME, then
those annotations can be queried at runtime by any java program.
Below example code shows how to query all given annotations at runtime.
Example:
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnoOne{
String key();
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnoTwo{
int count();
}
@MyAnnoTwo(count=20)
@MyAnnoOne(key="site", value="java2novice.com")
public void myAnnotationTestMethod(){
try {
Class<? extends MyMultipleAnns> cls = this.getClass();
Method mth = cls.getMethod("myAnnotationTestMethod");
Annotation[] anns = mth.getAnnotations();
for(Annotation an:anns){
System.out.println(an);
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Description:
We can assign default values to annotation members. These values will
be return in case if you didn't provide any values to the annotation
members.
We can assign default values by using default clause during members
declarations. Make sure that the default values are same type as members.
Below example shows how to assign default values to annotation
members.
Example:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnot{
@MyAnnot()
public void myAnnotationTestMethod(){
try {
Class<? extends MyAnnotDefaultValues> cls = this.getClass();
Method mth = cls.getMethod("myAnnotationTestMethod");
MyAnnot myAnno = mth.getAnnotation(MyAnnot.class);
System.out.println("key: "+myAnno.key());
System.out.println("value: "+myAnno.value());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Target Annotations
Annotations in java are used to associate metadata to program elements
like classes, methods, instance variables, etc.
There are mainly three types of annotations in java: Marker Annotation
(without any methods), Single-Valued Annotation (with a single
method), and Multi-Valued Annotation (with more than one method).
@Target annotation is a meta-annotation, i.e., it can only be used to
annotate other annotations.
It takes ElementType enumeration as its only argument. ElementType
enumeration is a constant which specifies the type of the program
element declaration (class, interface, constructor, etc.) to which the
annotation can be applied.
If we apply the @Target annotation with some ElementType as an
annotation to a custom annotation name CustomAnnotation, then
@CustomAnnotation can only be used to annotate those specific
elements types otherwise we will get an error.
The table below shows the element types, and the element declaration that can
be annotated are mentioned below as follows:
Field Field
Method Method
Constructor Constructor
Package PACKAGE
Element Type Element to be Annotated
Example:
/* Java program to Illustrate Targeted Annotations Importing required
classes from java.lang package */
import java.lang.annotation.*;
// Accessing the annotations used to annotate the class and storing them
//in an array of Annotation type since only one annotation is used to
// annotate our class therefore we print a[0]
Annotation a[] = obj.getClass().getAnnotations();
System.out.println(a[0]);
System.out.println(b[0]);
}
}
Student.java
//Utilizing the Annotation at Class level
@Course(cid="C-333",cname="Java",ccost=30000)
class Student
{
String sid;
String sname;
String saddr;
public Student(String sid,String sname,String saddr)
{
this.sid=sid;
this.sname=sname;
this.saddr=saddr;
}
// @Course()
public void getStudentDetails()
{
System.out.println("*****Student Course Details are*****");
System.out.println("-----------------------------");
System.out.println("Student id: "+sid);
System.out.println("Student name: "+sname);
System.out.println("Student Address: "+saddr);
}
}
UserDefAnnotation.java
import java.lang.annotation.*;
import java.lang.reflect.*;
class UserDefAnnotation
{
public static void main(String args[])throws Exception
{
Student std=new Student("S-111","Sreenidhi","Hyd");
std.getStudentDetails();
//Accessing data of Annotation
Class c=std.getClass();
//Method m=c.getMethod("getStudentDetails");
Annotation ann=c.getAnnotation(Course.class);
Course crs=(Course)ann;
System.out.println("Course id: "+crs.cid());
System.out.println("Course name: "+crs.cname());
System.out.println("Course Cost: "+crs.ccost());
}
}
import java.lang.annotation.*;
import java.lang.reflect.*;
class UserDefAnnotation
{
public static void main(String args[])throws Exception
{
Student std=new Student("S-111","Sreenidhi","Hyd");
std.getStudentDetails();
//Accessing data from Annotation
Class c=std.getClass();
Method m=c.getMethod("getStudentDetails");
Annotation ann=m.getAnnotation(Course.class);
Course crs=(Course)ann;
System.out.println("Course id: "+crs.cid());
System.out.println("Course name: "+crs.cname());
System.out.println("Course Cost: "+crs.ccost());
}
}
Output:
AnnotatedElement Interface
The getAnnotations() method of java.lang.AnnotatedElement class is used
to get the annotations present in the class implementing this interface. The
method returns an array of annotations present.
Syntax:
public Annotation[] getAnnotations()
Parameter: This method does not accepts any parameter.
Return Value: This method returns an array of annotations present.
Example:
// Java program to demonstrate getAnnotations() method
import java.lang.reflect.*;
import java.util.*;
import java.lang.annotation.*;
Annotation 1: @Deprecated
When an element has been deprecated, the Javadoc tag @deprecated tag
must be used. There is a difference between the @deprecated tag and
@Deprecated annotation.
Example
@Deprecated
public void Display()
System.out.println("Deprecateddemo display()");
d1.Display();
Output
Deprecateddemo display()
Annotation 2: @Override
A compile-time error occurs if the method does not override the method
from the superclass.
This ensures that the superclass method is overridden and not overloaded.
The code becomes more readable and maintenance issues can be
avoided.
Example
// Class 1
class ParentClass
t1.Display();
// Class 2
// Extending above class
@Override
Output
Annotation 3: @SuppressWarnings
There are two categories under which Java groups warnings - deprecated
and unchecked. When a legacy code interfaces with a code that uses
generics, an unchecked warning is generated.
Example
class DeprecatedDemo
@Deprecated
System.out.println("Deprecateddemo display()");
// Class 2
// warning
@SuppressWarnings({"checked", "deprecation"})
{
DeprecatedDemo d1 = new DeprecatedDemo();
d1.Display();
Output
Deprecateddemo display()
Annotation 4: @Documented
Annotation 5: @Target
The @Target annotation takes only one argument and this argument
should be a constant value from the ElementType enumeration.
The constants along with the corresponding declaration ars shown in the
table below:
CONSTRUCTOR Constructor
FIELD Field
METHOD Method
PACKAGE Package
PARAMETER Parameter
Class, Interface, or
TYPE
enumeration
@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE})
Annotation 6: @Inherited
Only the annotations that are used on class declarations are affected by it.
@Inherited causes the subclass to inherit the annotation from a
superclass. Hence, when there is a request for a specific annotation to a
subclass and it is not present in the subclass, the superclass is checked.
Example
package source;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// User-defined annotation
@Documented
@Retention(RetentionPolicy.RUNTIME)
@ interface AnnotationDemo
String Expirydate();
@AnnotationDemo(Developer="Ravi", Expirydate="26-03-2020")
void fun1()
}
@AnnotationDemo(Developer="Kiran", Expirydate="26-03-2021")
void fun2()
System.out.println("Welcome");
Output
Welcome
Use of Annotations
Functional Interface
Def:An interface which has only one abstract method is called “functional
interface”.
Example:
Example:
import java.lang.FunctionalInterface;
@FunctionalInterface
double getValue();
Description:
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 Classes in Java 7.
// anonymous class
@Override
}).start();
Output:
The lambda expression does not execute on its own. Instead, it is used to
implement a method defined by a functional interface.
() -> {
double pi = 3.1415;
return pi;
};
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 : Write a Java program that returns the value of Pi using the
lambda expression.
import java.lang.FunctionalInterface;
@FunctionalInterface
interface MyInterface{
// abstract method
double getPiValue();
MyInterface ref;
// lambda expression
ref = () -> { return 3.1415;}; (or)
ref = () ->3.1415;
Output:
Value of Pi = 3.1415
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,
Finally, we call the method getPiValue() using the reference interface. When
@FunctionalInterface
interface MyInterface {
// abstract method
result += str.charAt(i);
return result;
};
Output:
Lambda reversed = adbmaL
Syntax
() -> {
//Body of no parameter lambda
}
(p1) -> {
//Body of single parameter lambda
}
Syntax
(p1,p2) -> {
//Body of multiple parameter lambda
}
Output:
Drawing 10
Now, we are going to implement the above example with the help of Java
lambda expression.
//with lambda
Drawable d2=()->{
System.out.println("Drawing "+width);
};
d2.draw();
}
}
Output:
Drawing 10
A lambda expression can have zero or any number of arguments. Let's see the
examples:
interface Sayable{
public String say();
}
public class LambdaExpressionExample3{
public static void main(String[] args) {
Sayable s=()->{
return "I have nothing to say.";
};
System.out.println(s.say());
}
}
Output:
interface Sayable{
public String say(String name);
}
Output:
Hello, Sonoo
Hello, Sonoo
interface Addable{
int add(int a,int b);
}
Output:
30
300
In Java lambda expression, if there is only one statement, you may or may not
use return keyword. You must use return keyword when lambda expression
contains multiple statements.
interface Addable{
int add(int a,int b);
}
Output:
30
300
list.forEach( (n)->System.out.println(n) );
}
}
Output:
ankit
mayank
irfan
jai
@FunctionalInterface
interface Sayable{
String say(String message);
}
Output:
You can use lambda expression to run thread. In the following example, we are
implementing run method by using lambda expression.
Output:
Thread1 is running...
Thread2 is running...
Java lambda expression can be used in the collection framework. It provides
efficient and concise way to iterate, filter and fetch data. Following are some
lambda and collection examples provided.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Product{
int id;
String name;
float price;
public Product(int id, String name, float price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
}
public class LambdaExpressionExample10{
public static void main(String[] args) {
List<Product> list=new ArrayList<Product>();
//Adding Products
list.add(new Product(1,"HP Laptop",25000f));
list.add(new Product(3,"Keyboard",300f));
list.add(new Product(2,"Dell Mouse",150f));
}
}
Output:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
classz Product{
int id;
String name;
float price;
public Product(int id, String name, float price) {
super();
this.id = id;
this.name = name;
this.price = price;
}
}
public class LambdaExpressionExample11{
public static void main(String[] args) {
List<Product> list=new ArrayList<Product>();
list.add(new Product(1,"Samsung A5",17000f));
list.add(new Product(3,"Iphone 6S",65000f));
list.add(new Product(2,"Sony Xperia",25000f));
list.add(new Product(4,"Nokia Lumia",15000f));
list.add(new Product(5,"Redmi4 ",26000f));
list.add(new Product(6,"Lenevo Vibe",19000f));
// using lambda to filter data
Stream<Product> filtered_data = list.stream().filter(p -> p.price > 20000);
Output:
Sample Programs
1)
@functional_interface
interface Statement {
Statement s = () -> {
};
System.out.println(s.greet());
}
import java.util.ArrayList;
class Main {
// create an ArrayList
languages.add("java");
languages.add("swift");
languages.add("python");
Output
Note:
import java.util.ArrayList;
import java.util.Arrays;
class Main {
// create an ArrayList
languages.forEach((e) -> {
// body of lambda expression
result += e.charAt(i);
});
Output:
Note:
languages.forEach((e) -> {
result += e.charAt(i);
});
predefined Java
types(ArithmeticException,ArrayIndexOutOfBoundsException,etc.);
self-developed exceptions classes.
The example provides a lambda expression that returns the result of dividing
two numbers. The lambda expression code checks the divisor value. If this
value is 0, then a standard ArithmeticException is thrown with an appropriate
message.
interface IDivNumbers {
IDivNumbers ref;
try {
if (b==0)
catch (ArithmeticException e) {
return 0.0;
};
res = 0.0
interface INegativeRoot {
// Create an exception class that handles the square root of a negative number
NegativeRootException(String message) {
@SuppressWarnings("finally")
try {
// check for negative root with throwing an exception
if (t<0) {
t=0;
return Math.sqrt(t);
catch (NegativeRootException e) {
t = 0;
System.out.println(e.getMessage());
finally {
return t;
};
}
}
res = 0.0
import java.util.function.Function;
String x= "Hello";
x="a";
System.out.println(func1.apply("CVR College"));
Example 2:
import java.io.*;
// Interface
interface MyInterface {
void myFunction();
// Main class
class GFG {
// Custom initialization
};
intFace.myFunction();
gfg.data += 200;
Output:
Data : 170
Data : 670
Data : 870
Interface Calculator
Calculate();
}
Note:
Example:
MethodRefDemo.java
//Java Program to Illustrate How One can use Static method reference
interface Calculator
{
void calculate(int x,int y);
}
class Scientific
{
public static void findSum(int x,int y)
{
System.out.println("Sum="+(x+y));
}
}
class MethodRefDemo
{
public static void main(String args[])
{
//Reference to a static method
Calculator calc=Scientific::findSum;
calc.calculate(10,20);
}
}
Output:
Type 2: Reference to an instance method of a particular object
If a Lambda expression is like:
// If a lambda expression just call a default method of an object
(args) -> obj.instanceMethod(args)
Then method reference is like:
// Shorthand if a lambda expression just call a default method of an
object
objname::instanceMethod
Example:
interface Calculator
{
void calculate(int x,int y);
}
class Scientific
{
public static void findSum(int x,int y)
{
System.out.println("Sum="+(x+y));
}
public void findProduct(int x,int y)
{
System.out.println("Product="+(x*y));
}
}
class MethodRefDemo
{
public static void main(String args[])
{
//Reference to a static method
Calculator calc1=Scientific::findSum;
calc1.calculate(10,20);
//Referencing Instance method
Scientific sc=new Scientific();
Calculator calc2=sc::findProduct;
calc2.calculate(10,20);
}
}
Output:
Example:
interface ShapeFactory
class Shape
int x;
public Shape(int x)
this.x=x;
void area()
System.out.println("Area="+(x*x));
class MethodConRefDemo
ShapeFactory factory=Shape::new;
Shape shape=factory.getShape(10);
shape.area();
Output:
Example:
import java.util.*;
class User
String name;
this.name=name;
void Print()
System.out.println(name);
class MethArbitrary
forEach((User::Print));
Output:
Modules
Basics of modules
Advantages of Java SE 9 Module System
As Java SE 9 is going to divide JDK, JRE, JARs etc, into smaller modules, we
can use whatever modules we want. So it is very easy to scale down the Java
Application to Small devices.
Ease of Testing and Maintainability.
Supports better Performance.
As public is not just public, it supports very Strong Encapsulation. (Don’t worry
its a big concept. we will explore it with some useful examples soon).
We cannot access Internal Non-Critical APIs anymore.
Modules can hide unwanted and internal details very safely, we can get better
Security.
Application is too small because we can use only what ever modules we want.
Its easy to support Less Coupling between components.
Its easy to support Single Responsibility Principle (SRP).
JDK 9 Folder
Structure: Here
JDK 9 does NOT contain JRE. In JDK 9, JRE is separated into a separate
distribution folder. JDK 9 software contains a new folder “jmods”. It contains a
set of Java 9 Modules as shown below. In JDK 9, No rt.jar and No tools.jar
NOTE:- As of
today, “jmods” contains 95 modules. It may increase in the final release.
“jmods” folder is available at ${JAVA_HOME}/jmods. These are known as
JDK Modules.
As of now, Java 9 Module System has 95 modules in Early Access JDK. Oracle
Corp has separated JDK jars and Java SE Specifications into two set of
Modules.
Java 9 Module System has a “java.base” Module. It’s known as Base Module.
It’s an Independent module and does NOT dependent on any other modules. By
default, all other Modules dependent on this module. That’s why “java.base”
Module is also known as The Mother of Java 9 Modules. It’s default module for
all JDK Modules and User-Defined Modules.
requires
The requires directive indicates that this module depends on another module.
We used this directive in the previous posts, where the
module com.mydeveloperplanet.jpmshello depends on
module com.mydeveloperplanet.jpmshi.
1
requires com.mydeveloperplanet.jpmshi;
requires transitive <module name>: This means that any module that
reads your module implicitly also reads the transitive module — for
example, if your module contains a method which is publicly available
and returns a type of another module. When transitive is not used, any
module reading your module would explicitly have to add the dependent
module.
requires static <module name>: This is an optional dependency. The
module is needed at compile time, but not at runtime.
exports
The exports directive indicates which public types of the module's package are
accessible to other modules. We used this directive in the previous posts where
the package com.mydeveloperplanet.jpmshi was made accessible so that
module com.mydeveloperplanet.jpmshello was able to use the HiModules class.
exports com.mydeveloperplanet.jpmshi;
Remember you must have the javac command from the JDK installation on
your path (environment variable) for this command to work. Alternatively you
can replace the javac part in the command above with the full path to where
the javac command is located, like this:
Or
Javac –module-source-path src –d out –m moduleA
Or
The --module-path argument points to the root directory where all the compiled
modules are located. Remember, this is one level above the module root
directory.
The --module argument tells what module + main class to run. In the example
the module name is the com.jenkov.mymodule part and the main class name is
the com.jenkov.mymodule.Main . Notice how the module name and main class
name are separated by a slash (/) character.
Unnamed Module
From Java 9 and forward, all Java classes must be located in a module for
the Java VM to use them. But what do you do with older Java libraries
where you just have the compiled classes, or a JAR file?
In Java 9 you can still use the -classpath argument to the Java VM when
running an application. On the classpath you can include all your older
Java classes, just like you have done before Java 9. All classes found on
the classpath will be included in what Java calls the unnamed module.
The unnamed module exports all its packages. However, the classes in
the unnamed module are only readable by other classes in the unnamed
module - or from automatic modules (see next section). No named
module can read the classes of the unnamed module.
If a package is exported by a named module, but also found in the
unnamed module, the package from the named module will be used.
All classes in the unnamed module requires all modules found on the
module path. That way, all classes in the unnamed module can read all
classes exported by all the Java modules found on the module path.
Example:
Go to src directory
Introduction
Java 9 introduced the concept of modules to the Java platform. Modules change
the way we design and build Java applications. Even though their use is
optional, the JDK itself is now modularized, so we must at least know the basics
of the Java Platform Module System (JPMS).
The module system introduced in Java 9 makes it easier to organize your code.
Here’s a brief guide to working with modules in Java
In Java until now the class path has been the bottom line for what is available to
a running application. Although the class path serves this purpose and is well
understood, it ends up being a big, undifferentiated bucket into which all
dependencies are placed.
The module path adds a level above the class path. It serves as a container for
packages and determines what packages are available to the application.
We still have the option to deploying service providers on the class path (check out this
example).
module com.service.api {
exports com.service.api;
uses com.service.api.AnInterface;
}
A service provider will use "provides .. with" clause to declare what service interface it
intends to use (by using provides keyword) and what implementation of the interface it
wants to expose (by using with keyword).
module com.service.provider {
requires msg.service.api;
provides com.service.api.AnInterface with com.service.provider.AnInterfaceImpl;
}
We don't have to specify the service implementation in a file under the resource
directory META-INF/services. (Without modules, we still have to do that).
Example
In this example, we will create very simple service API module 'msg.service.api' which
'uses' a service interface to display a message. The example Provider will implement
the interface and will show the message in a Java Swing dialog. We will also create a
third project which will require the service interface and will have the provider
deployed during runtime via module path.
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
public interface MsgService {
msg.service.api/src/module-info.java
module msg.service.api {
exports msg.service;
uses msg.service.MsgService;
}
D:\java-modules\java-service-loader-example\msg.service.api>"tree /A /F"
|
\---src
| module-info.java
|
\---msg
\---service
MsgService.java
D:\java-modules\java-service-loader-example\msg.service.api>"tree /A /F"
| msg-service.jar
|
+---out
| | module-info.class
| |
| \---msg
| \---service
| MsgService.class
|
\---src
| module-info.java
|
\---msg
\---service
MsgService.java
import msg.service.MsgService;
import javax.swing.*;
msg.service.provider.swing/src/module-info.java
module msg.service.provider.swing {
requires msg.service.api;
requires java.desktop;
provides msg.service.MsgService with msg.provider.swing.MsgServiceImpl;
}
D:\java-modules\java-service-loader-example/msg.service.provider.swing>"tree
/A /F"
|
\---src
| module-info.java
|
\---msg
\---provider
\---swing
MsgServiceImpl.java
D:\java-modules\java-service-loader-
example\msg.service.provider.swing>mkdir lib
D:\java-modules\java-service-loader-example\msg.service.provider.swing>copy
..\msg.service.api\msg-service.jar lib\msg-service.jar
1 file(s) copied.
D:\java-modules\java-service-loader-example\msg.service.provider.swing>"tree
/A /F"
|
+---lib
| msg-service.jar
|
\---src
| module-info.java
|
\---msg
\---provider
\---swing
MsgServiceImpl.java
D:\java-modules\java-service-loader-
example\msg.service.provider.swing>javac -d out --module-path lib
src/module-info.java src/msg/provider/swing/MsgServiceImpl.java
D:\java-modules\java-service-loader-example\msg.service.provider.swing>jar --
create --file msg-service-swing.jar -C out .
D:\java-modules\java-service-loader-example\msg.service.provider.swing>"tree
/A /F"
| msg-service-swing.jar
|
+---lib
| msg-service.jar
|
+---out
| | module-info.class
| |
| \---msg
| \---provider
| \---swing
| MsgServiceImpl.class
|
\---src
| module-info.java
|
\---msg
\---provider
\---swing
MsgServiceImpl.java
import msg.service.MsgService;
import java.util.List;
my-app/src/module-info.java
module my.app {
requires msg.service.api;
}
D:\java-modules\java-service-loader-example/my-app>"tree /A /F"
|
\---src
| module-info.java
|
\---com
\---logicbig
AppMain.java
D:\java-modules\java-service-loader-example\my-app>mkdir lib
D:\java-modules\java-service-loader-example\my-app>copy
..\msg.service.api\msg-service.jar lib\msg-service.jar
1 file(s) copied.
D:\java-modules\java-service-loader-example\my-app>copy
..\msg.service.provider.swing\msg-service-swing.jar lib\msg-service-swing.jar
1 file(s) copied.
D:\java-modules\java-service-loader-example\my-app>"tree /A /F"
|
+---lib
| msg-service-swing.jar
| msg-service.jar
|
\---src
| module-info.java
|
\---com
\---logicbig
AppMain.java