Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
282 views

Java Architecture

The document discusses the Java architecture and its components. It explains that the Java architecture includes the Java Virtual Machine, Java Runtime Environment, and Java Development Kit. It also discusses how the Read-Eval-Print Loop can be used in Java to evaluate code without compiling.

Uploaded by

degadisa104
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
282 views

Java Architecture

The document discusses the Java architecture and its components. It explains that the Java architecture includes the Java Virtual Machine, Java Runtime Environment, and Java Development Kit. It also discusses how the Read-Eval-Print Loop can be used in Java to evaluate code without compiling.

Uploaded by

degadisa104
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 231

Java Architecture

Java Architecture is a collection of components, i.e., JVM, JRE, and JDK. It integrates
the process of interpretation and compilation. It defines all the processes involved in
creating a Java program. Java Architecture explains each and every step of how a
program is compiled and executed.

Java Architecture can be explained by using the following steps:

 There is a process of compilation and interpretation in Java.


 Java compiler converts the Java code into byte code.
 After that, the JVM converts the byte code into machine code.
 The machine code is then executed by the machine.

The following figure represents the Java Architecture in which each step is elaborate
graphically.
Now let's dive deep to get more knowledge about Java Architecture. As we know that
the Java architecture is a collection of components, so we will discuss each and every
component into detail.

Components of Java Architecture

The Java architecture includes the three main components:

 Java Virtual Machine (JVM)


 Java Runtime Environment (JRE)
 Java Development Kit (JDK)

Java Virtual Machine

 The main feature of Java is WORA. WORA stands for Write Once Run
Anywhere.
 The feature states that we can write our code once and use it anywhere or on any
operating system.
 Our Java program can run any of the platforms only because of the Java Virtual
Machine.
 It is a Java platform component that gives us an environment to execute java
programs.
 JVM's main task is to convert byte code into machine code.
 JVM, first of all, loads the code into memory and verifies it. After that, it executes
the code and provides a runtime environment.
Java Virtual Machine (JVM) has its own architecture, which is given below:

JVM Architecture

JVM is an abstract machine that provides the environment in which Java bytecode is
executed. The falling figure represents the architecture of the JVM.

ClassLoader: ClassLoader is a subsystem used to load class files. ClassLoader first loads
the Java code whenever we run it.

Class Method Area: In the memory, there is an area where the class data is stored during
the code's execution. Class method area holds the information of static variables, static
methods, static blocks, and instance methods.

Heap: The heap area is a part of the JVM memory and is created when the JVM starts up.
Its size cannot be static because it increase or decrease during the application runs.

Stack: It is also referred to as thread stack. It is created for a single execution thread. The
thread uses this area to store the elements like the partial result, local variable, data used
for calling method and returns etc.
Native Stack: It contains the information of all the native methods used in our
application.

Execution Engine: It is the central part of the JVM. Its main task is to execute the byte
code and execute the Java classes. The execution engine has three main components used
for executing Java classes.

o Interpreter: It converts the byte code into native code and executes. It
sequentially executes the code. The interpreters interpret continuously and even
the same method multiple times. This reduces the performance of the system, and
to solve this, the JIT compiler is introduced.
o JIT Compiler: JIT compiler is introduced to remove the drawback of the
interpreter. It increases the speed of execution and improves performance.
o Garbage Collector: The garbage collector is used to manage the memory, and it is
a program written in Java. It works in two phases, i.e., Mark and Sweep. Mark is
an area where the garbage collector identifies the used and unused chunks of
memory. The Sweep removes the identified object from the Mark

Java Native Interface

Java Native Interface works as a mediator between Java method calls and native libraries.

Java Runtime Environment

It provides an environment in which Java programs are executed. JRE takes our Java code,
integrates it with the required libraries, and then starts the JVM to execute it. To learn
more about the Java Runtime Environment, click here.

Java Development Kit

It is a software development environment used in the development of Java applications


and applets. Java Development Kit holds JRE, a compiler, an interpreter or loader, and
several development tools in it. To learn more about the Java Development Kit, click here.

These are three main components of Java Architecture. The execution of a program is
done with all these three components.
Read-Eval-Print Loop (REPL) in Java

The Read-Eval-Print Loop or REPL is a shell interface. This interface reads and
evaluates each line of input and then prints the result. The Read-Eval-Print Loop helps
us to interact with our application runtime present in a specific state. The commands are
read and evaluated by the REPL and print the result. After printing the result, REPL goes
back to the start to read, evaluate and print our next input.

Using REPL, we can easily write and test our Java code without compiling it and can see
the output directly on the console.

Java doesn't have REPL already?

Definitely, a REPL must be in an established language like Java. But, not all languages
have the REPL, and Java is one of them. The Java developers have required it most. Java
has had something like REPL for a while as Java Beanshell. But the project was not a fully-
featured REPL with other languages. For this, in 2016, Java 9 was released, which deliver a
full function REPL environment.

Why is REPL so helpful?

By using the REPL, we don't need to compile or test our Java code using the javac
command. After using the REPL,
1. No need of an editor to write the Java program.
2. No need to save the Java program.
3. No need to compile Java program.
4. No need to do editing if any compile-time or runtime error comes.
5. No need to repeat the process.

We can evaluate methods, classes, and statements without creating a class. The "Hello
World" program can also be written without creating a class.

Requirements for using REPL

There is only one requirement to use REPL,i.e., we should have Java 9 or higher version
in our system. If Java 9 is installed in our system, we are ready to use REPL. In order to
check the current version of Java in your system, open the command prompt and type the
following command:
1. java -version

Using REPL

Below are some examples of REPL in which we evaluate the mathematical expressions,
calculate the Fibonacci series, create a dynamic class, know the history, and modify the
class.

Example 1: Evaluating Mathematical Expressions

1. jshell> double a = 10;


2. jshell> a= Math.pow(a, 2);
3.
4. jshell> a+20
5. jshell> /vars
6. jshell> double data = Math.pow(8.3, 5);

Description:

In the first line, we create a variable "a" of type double and set its initial value 10. After
that, we find the square of variable "a" and store it in the same variable. After that, we
simply add 20 to the variable "a". The Jshell will put the result into a temporary
variable "$3". Next, we execute the "/vars" command, which shows us all the created
variables. At last, we create a variable "data" of type double and store the 5th power of
digit 8.3.

Output:
Example 2: Calculating Fibonacci Series

1. jshell> int fibo(int no){


2. ...> if((no == 0) || (no == 1))
3. ...> return no;e all possible completions; total possible completions
4. ...> else
5. ...> return fibo(no-1)+fibo(no-2);
6. ...> }
7. jshell> /methods
8. jshell> fibo(11)
9. jshell> fibo(12)
10. jshell> int[] arr = { 1,2,3,4,5,6};
11. jshell> for(int i: arr){
12. ...> System.out.println(fibo(i));
13. ...> }
Description:

In the first six lines of code, we create a method for the Fibonacci series. After that, we
use the /methods command of Jshell, which shows us all the available methods. In the
next two lines, we test the fibo() method by passing integer values. We create an
array arr to determine how many terms we want to get the Fibonacci series. Next, we
iterate each value of arr using for each loop. We pass each value of the arr to the fibo()
method and print its return value.

Output:
Example 3: REPL for re-use

1. jshell> int fibo(int no){


2. ...> return 2;
3. ...> }
4. jshell> for(int i: arr){
5. ...> System.out.println(fibo(i));
6. ...> }

Description:

In the above code, we create a fibo() method with same return type and argument which
we have created before. At this time, the Jshell overrides the previous "fibo()" method
with the current one. Next, we pass each value of the arr to the function to ensure
whether our fibo() method is override or not.

Output:

Example 4: Defining the class

1. jshell> class Student{


2. ...> public String Name;
3. ...> public int age;
4. ...> public String course;
5. ...> public int semester;
6. ...> public Student(String Name, int age, String course, int semester){
7. ...> this.Name=Name;
8. ...> this.age=age;
9. ...> this.course = course;
10. ...> this.semester=semester;
11. ...> }
12. ...> public void showData(){
13. ...> System.out.println("Name= "+ Name);
14. ...> System.out.println("Age= "+ age);
15. ...> System.out.println("Course= "+ course);
16. ...> System.out.println("Semester= "+semester);
17. ...> }
18. ...> }

Description:

In the above code, we create class "Student", which have Name, age, course and
semester. We create a constructor in which we set the values to these variables. After the
constructor, we create a method that shows the value of all the variables for each instance
of the class.
Output:

Example 5: Creating an instance of the class

1. jshell> Student s1 = new Student( "Shubham Rastogi", 18, "MCA", 4);


2. jshell> Student s2 = new Student( "Kartik Rastogi", 23, "MCA", 3);
3. jshell> /vars
4. jshell> s1.showData();
5. jshell> s2.showData();

Description:

In the above code, we create two instances of the class and pass the value to the
constructor for all the class variables. Next, we run the Jshell command to check whether
s1 and s2 variables are created or not. At last, we call the showData() method to display
data of each instance.

Output:
Types of Exception in Java

In Java, exception is an event that occurs during the execution of a program and disrupts
the normal flow of the program's instructions. Bugs or errors that we don't want and
restrict our program's normal execution of code are referred to as exceptions. In this
section, we will focus on the types of exceptions in Java and the differences between
the two.

Exceptions can be categorized into two ways:

1. Built-in Exceptions
 Checked Exception
 Unchecked Exception
2. User-Defined Exceptions
Built-in Exception

Exceptions that are already available in Java libraries are referred to as built-in
exception. These exceptions are able to define the error situation so that we can
understand the reason of getting this error. It can be categorized into two broad
categories, i.e., checked exceptions and unchecked exception.

Checked Exception

Checked exceptions are called compile-time exceptions because these exceptions are
checked at compile-time by the compiler. The compiler ensures whether the programmer
handles the exception or not. The programmer should have to handle the exception;
otherwise, the system has shown a compilation error.

CheckedExceptionExample.java

1. import java.io.*;
2. class CheckedExceptionExample {
3. public static void main(String args[]) {
4. FileInputStream file_data = null;
5. file_data = new FileInputStream("C:/Users/ajeet/OneDrive/Desktop/Hello.txt");
6. int m;
7. while(( m = file_data.read() ) != -1) {
8. System.out.print((char)m);
9. }
10. file_data.close();
11. }
12. }

In the above code, we are trying to read the Hello.txt file and display its data or content
on the screen. The program throws the following exceptions:

1. The FileInputStream(File filename) constructor throws


the FileNotFoundException that is checked exception.
2. The read() method of the FileInputStream class throws the IOException.
3. The close() method also throws the IOException.

Output:
How to resolve the error?

There are basically two ways through which we can solve these errors.

1) The exceptions occur in the main method. We can get rid from these compilation
errors by declaring the exception in the main method using the throws We only declare
the IOException, not FileNotFoundException, because of the child-parent relationship.
The IOException class is the parent class of FileNotFoundException, so this exception will
automatically cover by IOException. We will declare the exception in the following way:

1. class Exception{
2. public static void main(String args[]) throws IOException {
3. ...
4. ...
5. }

If we compile and run the code, the errors will disappear, and we will see the data of the
file.

2) We can also handle these exception using try-catch However, the way which we have
used above is not correct. We have to a give meaningful message for each exception type.
By doing that it would be easy to understand the error. We will use the try-catch block in
the following way:

Exception.java

1. import java.io.*;
2. class Exception{
3. public static void main(String args[]) {
4. FileInputStream file_data = null;
5. try{
6. file_data = new FileInputStream("C:/Users/ajeet/OneDrive/Desktop/programs/
Hell.txt");
7. }catch(FileNotFoundException fnfe){
8. System.out.println("File Not Found!");
9. }
10. int m;
11. try{
12. while(( m = file_data.read() ) != -1) {
13. System.out.print((char)m);
14. }
15. file_data.close();
16. }catch(IOException ioe){
17. System.out.println("I/O error occurred: "+ioe);
18. }
19. }
20. }

We will see a proper error message "File Not Found!" on the console because there is no
such file in that location.

Unchecked Exceptions

The unchecked exceptions are just opposite to the checked exceptions. The compiler
will not check these exceptions at compile time. In simple words, if a program throws an
unchecked exception, and even if we didn't handle or declare it, the program would not
give a compilation error. Usually, it occurs when the user provides bad data during the
interaction with the program.
Note: The RuntimeException class is able to resolve all the unchecked exceptions because of
the child-parent relationship.

UncheckedExceptionExample1.java

1. class UncheckedExceptionExample1 {
2. public static void main(String args[])
3. {
4. int postive = 35;
5. int zero = 0;
6. int result = positive/zero;
7. //Give Unchecked Exception here.
8. System.out.println(result);
9. }
10. }

In the above program, we have divided 35 by 0. The code would be compiled successfully,
but it will throw an ArithmeticException error at runtime. On dividing a number by 0
throws the divide by zero exception that is a uncheck exception.

Output:

UncheckedException1.java

1. class UncheckedException1 {
2. public static void main(String args[])
3. {
4. int num[] ={10,20,30,40,50,60};
5. System.out.println(num[7]);
6. }
7. }

Output:

In the above code, we are trying to get the element located at position 7, but the length of
the array is 6. The code compiles successfully, but throws the
ArrayIndexOutOfBoundsException at runtime.

User-defined Exception

In Java, we already have some built-in exception classes


like ArrayIndexOutOfBoundsException, NullPointerException,
and ArithmeticException.

These exceptions are restricted to trigger on some predefined conditions. In Java, we can
write our own exception class by extends the Exception class. We can throw our own
exception on a particular condition using the throw keyword. For creating a user-defined
exception, we should have basic knowledge of the try-catch block and throw keyword.

Let's write a Java program and create user-defined exception.

ADVERTISEMENT

ADVERTISEMENT

UserDefinedException.java

1. import java.util.*;
2. class UserDefinedException{
3. public static void main(String args[]){
4. try{
5. throw new NewException(5);
6. }
7. catch(NewException ex){
8. System.out.println(ex) ;
9. }
10. }
11. }
12. class NewException extends Exception{
13. int x;
14. NewException(int y) {
15. x=y;
16. }
17. public String toString(){
18. return ("Exception value = "+x) ;
19. }
20. }

Output:

Description:

In the above code, we have created two classes,


i.e., UserDefinedException and NewException. The UserDefinedException has our
main method, and the NewException class is our user-defined exception class, which
extends exception. In the NewException class, we create a variable x of type integer and
assign a value to it in the constructor. After assigning a value to that variable, we return
the exception message.
In the UserDefinedException class, we have added a try-catch block. In the try section,
we throw the exception, i.e., NewException and pass an integer to it. The value will be
passed to the NewException class and return a message. We catch that message in the
catch block and show it on the screen.

Difference Between Checked and Unchecked Exception

S.N Checked Exception Unchecked Exception


o

1. These exceptions are checked at These exceptions are just opposite to the
compile time. These exceptions are checked exceptions. These exceptions
handled at compile time too. are not checked and handled at compile
time.

2. These exceptions are direct They are the direct subclasses of the
subclasses of exception but not RuntimeException class.
extended from RuntimeException
class.

3. The code gives a compilation error in The code compiles without any error
the case when a method throws a because the exceptions escape the notice
checked exception. The compiler is of the compiler. These exceptions are the
not able to handle the exception on results of user-created errors in
its own. programming logic.

4. These exceptions mostly occur when These exceptions occur mostly due to
the probability of failure is too high. programming mistakes.

5. Common checked exceptions include Common unchecked exceptions include


IOException, DataAccessException, ArithmeticException,
InterruptedException, etc. InvalidClassException,
NullPointerException, etc.

6. These exceptions are propagated These are automatically propagated.


using the throws keyword.

7. It is required to provide the try-catch In the case of unchecked exception it is


and try-finally block to handle the not mandatory.
checked exception.

Bugs or errors that we don't want and restrict the normal execution of the programs are
referred to as exceptions.

ArithmeticException, ArrayIndexOutOfBoundExceptions,
ClassNotFoundExceptions etc. are come in the category of Built-in Exception.
Sometimes, the built-in exceptions are not sufficient to explain or describe certain
situations. For describing these situations, we have to create our own exceptions by
creating an exception class as a subclass of the Exception class. These types of exceptions
come in the category of User-Defined Exception.

Why String is Immutable or Final in Java

In object-oriented programming, the immutable string or objects that cannot be


modified once it is created. But we can only change the reference to the object. We
restrict to change the object itself. The String is immutable in Java because of the
security, synchronization and concurrency, caching, and class loading. The reason of
making string final is to destroy the immutability and to not allow others to extend it.

The String objects are cached in the String pool, and it makes the String immutable. The
cached String literals are accessed by multiple clients. So, there is always a risk, where
action performs by one client affects all other clients. For example, if one client performs
an action and changes the string value from Pressure to PRESSURE, all remaining clients
will also read that value. For the performance reason, caching of String objects was
important, so to remove that risk, we have to make the String Immutable.
These are some more reasons of making String immutable:

 The String pool cannot be possible if String is not immutable in Java. A lot of heap
space is saved by JRE. The same string variable can be referred to by more than one
string variable in the pool. String interning can also not be possible if the String
would not be immutable.
 If we don't make the String immutable, it will pose a serious security threat to the
application. For example, database usernames, passwords are passed as strings to
receive database connections. The socket programming host and port descriptions
are also passed as strings. The String is immutable, so its value cannot be changed.
If the String doesn't remain immutable, any hacker can cause a security issue in
the application by changing the reference value.
 The String is safe for multithreading because of its immutableness. Different
threads can access a single "String instance". It removes the synchronization for
thread safety because we make strings thread-safe implicitly.
 Immutability gives the security of loading the correct class by Classloader. For
example, suppose we have an instance where we try to load java.sql.Connection
class but the changes in the referenced value to the myhacked.Connection class
does unwanted things to our database.

Let's understand the concept of immutable through an example.

ImmutableString.java
1. import java.util.*;
2. class ImmutableString{
3. public static void main(String args[]){
4. String NewString = "Hello";
5. NewString.concat("World");
6. System.out.println(NewString);
7. }
8. }

Output:

Description: We can understand the above example with the help of the following
diagram:
In the string constant pool, the Hello remains unchanged, and a new string object is
created with HelloWorld. It shows that the strings are immutable. The reference variable
points to the Hello not to the HelloWorld.

If we want that it refers to the HelloWorld, we have to explicitly assign it to that variable.
For example:

1. import java.util.*;
2. class ImmutableString{
3. public static void main(String args[]){
4. String NewString = "Hello";
5. NewString = NewString.concat("World");
6. System.out.println(NewString);
7. }
8. }

Output:
Set in Java
The set is an interface available in the java.util package. The set interface extends the
Collection interface. An unordered collection or list in which duplicates are not allowed
is referred to as a collection interface. The set interface is used to create the
mathematical set. The set interface use collection interface's methods to avoid the
insertion of the same elements. SortedSet and NavigableSet are two interfaces that
extend the set implementation.

In the above diagram, the NavigableSet and SortedSet are both the interfaces.
The NavigableSet extends the SortedSet, so it will not retain the insertion order and
store the data in a sorted way.

SetExample1.java

1. import java.util.*;
2. public class setExample{
3. public static void main(String[] args)
4. {
5. // creating LinkedHashSet using the Set
6. Set<String> data = new LinkedHashSet<String>();
7.
8. data.add("JavaTpoint");
9. data.add("Set");
10. data.add("Example");
11. data.add("Set");
12.
13. System.out.println(data);
14. }
15. }

Output:

Note: Throughout the section, we have compiled the program with file name and run the
program with class name. Because the file name and the class name are different.

Operations on the Set Interface


On the Set, we can perform all the basic mathematical operations like intersection, union
and difference.

Suppose, we have two sets, i.e., set1 = [22, 45, 33, 66, 55, 34, 77] and set2 = [33, 2, 83,
45, 3, 12, 55]. We can perform the following operation on the Set:

o Intersection: The intersection operation returns all those elements which are present in
both the set. The intersection of set1 and set2 will be [33, 45, 55].
o Union: The union operation returns all the elements of set1 and set2 in a single set, and
that set can either be set1 or set2. The union of set1 and set2 will be [2, 3, 12, 22, 33, 34,
45, 55, 66, 77, 83].
o Difference: The difference operation deletes the values from the set which are present in
another set. The difference of the set1 and set2 will be [66, 34, 22, 77].

In set, addAll() method is used to perform the union, retainAll() method is used to
perform the intersection and removeAll() method is used to perform difference. Let's
take an example to understand how these methods are used to perform the
intersection, union, and difference operations.

SetExample2.java

1. import java.util.*;
2. public class SetOperations
3. {
4. public static void main(String args[])
5. {
6. Integer[] A = {22, 45,33, 66, 55, 34, 77};
7. Integer[] B = {33, 2, 83, 45, 3, 12, 55};
8. Set<Integer> set1 = new HashSet<Integer>();
9. set1.addAll(Arrays.asList(A));
10. Set<Integer> set2 = new HashSet<Integer>();
11. set2.addAll(Arrays.asList(B));
12.
13. // Finding Union of set1 and set2
14. Set<Integer> union_data = new HashSet<Integer>(set1);
15. union_data.addAll(set2);
16. System.out.print("Union of set1 and set2 is:");
17. System.out.println(union_data);
18.
19. // Finding Intersection of set1 and set2
20. Set<Integer> intersection_data = new HashSet<Integer>(set1);
21. intersection_data.retainAll(set2);
22. System.out.print("Intersection of set1 and set2 is:");
23. System.out.println(intersection_data);
24.
25. // Finding Difference of set1 and set2
26. Set<Integer> difference_data = new HashSet<Integer>(set1);
27. difference_data.removeAll(set2);
28. System.out.print("Difference of set1 and set2 is:");
29. System.out.println(difference_data);
30. }
31. }

Output:

Description:
In the above code, first, we create two arrays, i.e., A and B of type integer. After that, we
create two set, i.e., set1 and set2 of type integer. We convert both the array into a list
and add the elements of array A into set1 and elements of array B into set2.

For performing the union, we create a new set union_data with the same element of the
set1. We then call the addAll() method of set and pass the set2 as an argument to it.
This method will add all those elements to the union_data which are not present in it
and gives the union of both sets.

For performing the intersection, we create a new set intersection_data with the same
element of the set1. We then call the retainAll() method of set and pass the set2 as an
argument to it. This method will get all those elements from
the intersection_data which are present in set2 and store it in the intersection_data.
Now, the intersection_data contains the intersect value of both the sets.
For performing the difference, we create a new set difference_data with the same
element of the set1. We then call the removeAll() method of set and pass the set2 as an
argument to it. This method will remove all those elements from
the difference_data which are present in the set2 and gives the difference of both the
sets.

Set Methods
There are several methods available in the set interface which we can use to perform a
certain operation on our sets. These methods are as follows:

1) add()
The add() method insert a new value to the set. The method returns true and false
depending on the presence of the insertion element. It returns false if the element is
already present in the set and returns true if it is not present in the set.

Syntax:

1. boolean add(type element).

SetExample3.java

1. import java.io.*;
2. import java.util.*;
3. public class addMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(11);
11. data.add(61);
12. data.add(51);
13. System.out.println("data: " + data);
14. }
15. }

Output:

2) addAll()
The addAll() method appends all the elements of the specified collection to the set.

Syntax:

1. boolean addAll(Collection data)

SetExample4.java

1. import java.io.*;
2. import java.util.*;
3. class addAllMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. System.out.println("Set: " + data);
11. ArrayList<Integer> newData = new ArrayList<Integer>();
12. newData.add(91);
13. newData.add(71);
14. newData.add(81);
15. data.addAll(newData);
16. System.out.println("Set: " + data);
17. }
18. }

Output:

3) clear()
The method removes all the elements from the set. It doesn't delete the reference of the
set. It only deletes the elements of the set.

Syntax:

1. void clear()
ADVERTISEMENT

ADVERTISEMENT

SetExample5.java

1. import java.io.*;
2. import java.util.*;
3. public class clearMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7.
8. data.add(31);
9. data.add(21);
10. data.add(41);
11. System.out.println("Set: " + data);
12.
13. data.clear();
14. System.out.println("The final set: " + data);
15. }
16. }

Output:

4) contains()
The contains() method is used to know the presence of an element in the set. Its return
value is true or false depending on the presence of the element.

Syntax:

1. boolean contains(Object element)

SetExample6.java

1. import java.io.*;
2. import java.util.*;
3. class containsMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(51);
11. data.add(11);
12. data.add(81);
13. System.out.println("Set: " + data);
14. System.out.println("Does the Set contains '91'?" + data.contains(91));
15. System.out.println("Does the Set contains 'javaTpoint'? " + data.contains("4"));
16. System.out.println("Does the Set contains '51'? " + data.contains(51));
17. }
18. }

Output:

5) containsAll()
The method is used to check whether all the elements of the collection are available in
the existing set or not. It returns true if all the elements of the collection are present in
the set and returns false even if one of the elements is missing in the existing set.

Syntax:

1. public boolean containsAll(Collection data)

SetExample7.java

1. import java.io.*;
2. import java.util.*;
3. class containsAllMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(51);
11. data.add(11);
12. data.add(81);
13.
14. System.out.println("data: " + data);
15.
16. Set<Integer> newData = new LinkedHashSet<Integer>();
17. newData.add(31);
18. newData.add(21);
19. newData.add(41);
20.
21. System.out.println("\nDoes data contains newData?: "+ data.containsAll(newData));
22.
23. }
24. }

Output:
6) hashCode()
The method is used to derive the hash code value for the current instance of the set. It
returns hash code value of integer type.

Syntax:

1. public int hashCode()

SetExample8.java

1. import java.io.*;
2. import java.util.*;
3. class hashCodeMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(51);
11. data.add(11);
12. data.add(81);
13. System.out.println("data: " + data);
14. System.out.println("\nThe hash code value of set is:"+ data.hashCode());
15. }
16. }

Output:
7) isEmpty()
The isEmpty() method is used to identify the emptiness of the set . It returns true if the
set is empty and returns false if the set is not empty.

Syntax:

1. boolean isEmpty()

SetExample9.java

1. import java.io.*;
2. import java.util.*;
3. class isEmptyMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(51);
11. data.add(11);
12. data.add(81);
13. System.out.println("data: " + data);
14. System.out.println("\nIs data empty?: "+ data.isEmpty());
15. }
16. }
Output:

8) iterator()
The iterator() method is used to find the iterator of the set. The iterator is used to get
the element one by one.

ADVERTISEMENT

Syntax:

1. Iterator iterate_value = set1.iterator();

SetExample10.java

1. import java.io.*;
2. import java.util.*;
3. class iteratorMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(51);
11. data.add(11);
12. data.add(81);
13. System.out.println("data: " + data);
14.
15. Iterator newData = data.iterator();
16. System.out.println("The NewData values are: ");
17. while (newData.hasNext()) {
18. System.out.println(newData.next());
19. }
20. }
21. }

Output:

9) remove()
The method is used to remove a specified element from the Set. Its return value
depends on the availability of the element. It returns true if the element is available in
the set and returns false if it is unavailable in the set.

Syntax:

1. boolean remove(Object O)

SetExample11.java

1. import java.io.*;
2. import java.util.*;
3. class removeMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(51);
11. data.add(11);
12. data.add(81);
13. System.out.println("data: " + data);
14.
15. data.remove(81);
16. data.remove(21);
17. data.remove(11);
18. System.out.println("data after removing elements: " + data);
19. }
20. }

Output:

11) removeAll()
The method removes all the elements of the existing set from the specified collection.

Syntax:

1. public boolean removeAll(Collection data)


SetExample12.java

1. import java.io.*;
2. import java.util.*;
3. class removeAllMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(91);
11. data.add(71);
12. data.add(81);
13. System.out.println("data: " + data);
14.
15. ArrayList<Integer> newData = new ArrayList<Integer>();
16. newData.add(91);
17. newData.add(71);
18. newData.add(81);
19. System.out.println("NewData: " + newData);
20.
21. data.removeAll(newData);
22. System.out.println("data after removing Newdata elements : " + data);
23. }
24. }

Output:
11) retainAll()
The method retains all the elements from the set specified in the given collection.

Syntax:

1. public boolean retainAll(Collection data)

SetExample13.java

1. import java.io.*;
2. import java.util.*;
3. class retainAllMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(91);
11. data.add(71);
12. data.add(81);
13. System.out.println("data: " + data);
14.
15. ArrayList<Integer> newData = new ArrayList<Integer>();
16. newData.add(91);
17. newData.add(71);
18. newData.add(81);
19. System.out.println("newData: " + newData);
20.
21. data.retainAll(newData);
22. System.out.println("data after retaining newdata elements : " + data);
23. }
24. }

Output:

12) size()
The method returns the size of the set.

Syntax:

1. int size()

SetExample14.java

1. import java.io.*;
2. import java.util.*;
3. class sizeMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(91);
11. data.add(71);
12. data.add(81);
13. System.out.println("data: " + data);
14.
15. System.out.println("size of the data is : " + data.size());
16. }
17. }

Output:

13) removeAll()
The method is used to create an array with the same elements of the set.

Syntax:

1. Object[] toArray()

SetExample15.java

1. import java.io.*;
2. import java.util.*;
3. class toArrayMethod {
4. public static void main(String args[])
5. {
6. Set<Integer> data = new LinkedHashSet<Integer>();
7. data.add(31);
8. data.add(21);
9. data.add(41);
10. data.add(91);
11. data.add(71);
12. data.add(81);
13. System.out.println("data: " + data);
14.
15. Object[] array_data = data.toArray();
16. System.out.println("The array is:");
17. for (int i = 0; i < array_data.length; i++)
18. System.out.println(array_data[i]);
19. }
20. }

Output:
Types of Classes in Java

In Java, the class is a blueprint from which we can create an individual object. Java
provides a keyword named class by which we can declare a class. Inside the class, we
define class members and functions. It is not possible to create Java programs without
class. We can also refer a class as a user-defined data type because an object-oriented
paradigm allows us to model real-world objects. In this section, we will focus on
the types of classes in Java.

Types of Classes

There are seven types of classes in Java:

1. Static Class
2. Final Class
3. Abstract Class
4. Concrete Class
5. Singleton Class
6. POJO Class
7. Inner Class
Static Class

In Java, static is a keyword that manage objects in the memory. The static object belongs
to the class instead of the instance of the class.

We can make a class static if and only if it is a nested class. We can also say that static
classes are known as nested classes. It means that a class that is declared as static within
another class is known as a static class. Nested static class does not require reference to
the outer class. The purpose of a static class is to provide the outline of its inherited class.

PlayNext
Unmute

Current Time 0:00

Duration 18:10
Loaded: 0.37%
Â
Fullscreen
Backward Skip 10sPlay VideoForward Skip 10s
The properties of the static class are:

o The class has only static members.


o It cannot access the member (non-static) of the outer class.
o We cannot create an object of the static class.

Let's understand the concept of static class through a program.

StaticClassExample.java

1. public class StaticClassExample


2. {
3. private static String str = "Javatpoint";
4. //nested class which is a Static class
5. public static class StaticDemo
6. {
7. //non-static method of Static class
8. public void show()
9. {
10. System.out.println(str);
11. }
12. }
13. public static void main(String args[])
14. {
15. StaticClassExample.StaticDemo obj = new StaticClassExample.StaticDemo();
16. obj.show();
17. }
18. }

Output:

Javatpoint

In the outer class of the above program, we have declared a variable str as static because
we are accessing that variable from a static context. If we declare that variable as non-
static, the compiler shows an error because a nested static class cannot access non-
static members of the outer class.
The second thing to be noticed in the above program is that for creating the object of the
nested class we need not to create an instance of the outer class. If the nested class is not
a static class, we need to create an instance of the outer class.

Final Class

The word final means that cannot be changed. The final class in Java can be declared
using the final keyword. Once we declare a class as final, the values remain the same
throughout the program. The purpose of the final class is to make the
class immutable like the String class. It is only a way to make the class immutable.
Remember that the final class cannot be extended. It also prevents the class from
being sub-classed.

Let's understand the concept of the final class through a program.

FinalClassExample.java

1. //base class declared as final


2. final class A
3. {
4. void printmsg()
5. {
6. System.out.print("Base class method is executed.");
7. }
8. }
9. //derived class
10. //extending a final class which is not possible
11. //it shows the error cannot inherit final class at compile time
12. class B extends A
13. {
14. void printmsg()
15. {
16. System.out.print("Derived class method is executed.");
17. }
18. }
19. //main class
20. public class FinalClassExample
21. {
22. public static void main(String[] arg)
23. {
24. B obj = new B();
25. obj.printmsg();
26. }
27. }

Output:

/FinalClassExample.java:11: error: cannot inherit from final A class B extends A

Abstract Class

An abstract class is a that is declared with the keyword abstract. The class may or may
not contain abstract methods. We cannot create an instance of an abstract class but it can
be a subclass. These classes are incomplete, so to complete the abstract class we should
extend the abstract classes to a concrete class. When we declare a subclass as abstract
then it is necessary to provide the implementation of abstract methods. Therefore, the
subclass must also be declared abstract. We can achieve data hiding by using the abstract
class. An example of an abstract class is AbstarctMap class that is a part of the
Collections framework.

Let's understand the concept of abstract class through a program.

AbstractClassExample.java

1. //abstract class
2. abstract class MathematicalOperations
3. {
4. int a=30, b=40;
5. //abstract method
6. public abstract void add();
7. }
8. public class Operation extends MathematicalOperations
9. {
10. //definition of abstract method
11. public void add()
12. {
13. System.out.println("Sum of a and b is: "a+b);
14. }
15. public static void main(String args[])
16. {
17. MathematicalOperations obj = new Operation();
18. obj.add();
19. }
20. }

Output:

Sum of a and b is: 70

Concrete Class

These are the regular Java classes. A derived class that provides the basic implementations
for all of the methods that are not already implemented in the base class is known as
a concrete class. In other words, it is regular Java classes in which all the methods of an
abstract class are implemented. We can create an object of the concrete class directly.
Remember that concrete class and abstract class are not the same. A concrete class may
extend its parent class. It is used for specific requirements.

Let's understand the concept of the concrete class through a program.

ConcreteClassExample.java

1. //Concrete Class
2. public class ConcreteClassExample
3. {
4. //method of the concreted class
5. static int product(int a, int b)
6. {
7. return a * b;
8. }
9. public static void main(String args[])
10. {
11. //method calling
12. int p = product(6, 8);
13. System.out.println("Product of a and b is: " + p);
14. }
15. }

Output:

Product of a and b is: 48

Singleton Class

A class that has only an object at a time is known as a singleton class. Still, if we are
trying to create an instance a second time, that newly created instance points to the first
instance. If we made any alteration inside the class through any instance, the
modification affects the variable of the single instance, also. It is usually used to control
access while dealing with the database connection and socket programming. If we want
to create a singleton class, do the following:

o Create a private constructor.


o Create a static method (by using the lazy initialization) that returns the object of
the singleton class.

SingletonClassExample.java

1. public class Singleton


2. {
3. private String objectState;
4. private static Singleton instance = null;
5. private Singleton() throws Exception
6. {
7. this.objectState = "Javatpoint";
8. }
9. public static Singleton getInstance()
10. {
11. if(instance==null)
12. {
13. try
14. {
15. instance=new Singleton();
16. }
17. catch(Exception e)
18. {
19. e.printStackTrace();
20. }
21. }
22. return instance;
23. }
24. public String getObjectState()
25. {
26. return objectState;
27. }
28. public void setObjectState(String objectState)
29. {
30. this.objectState = objectState;
31. }
32. }

Output:

Javatpoint

POJO Class

In Java, POJO stands for Plain Old Java Object. A Java class that contains only private
variables, setter and getter is known as POJO class. It is used to define Java objects that
increase the reusability and readability of a Java program. The class provides
encapsulation. It is widely used in Java because it is easy to understand these classes.
POJO class has the following properties:

o It does not extend the predefined classes such as Arrays, HttpServlet, etc.
o It cannot contain pre-specified annotations.
o It cannot implement pre-defined interfaces.
o It is not required to add any constructor.
o All instance variables must be private.
o The getter/ setter methods must be public.

Let's understand the concept of POJO class through a Java program.


PojoClassExample.java

1. class PojoDemo
2. {
3. //private variable
4. private double price=89764.34;
5. //getter method
6. public double getPrice()
7. {
8. return price;
9. }
10. //setter method
11. public void setPrice(int price)
12. {
13. this.price = price;
14. }
15. }
16. //main class
17. public class PojoClassExample
18. {
19. public static void main(String args[])
20. {
21. PojoDemo obj = new PojoDemo();
22. System.out.println("The price of an article is "+ obj.getPrice()+" Rs.");
23. }
24. }

Output:

The price of an article is 89764.34 Rs.

Inner class

Java allows us to define a class within a class and such classes are known as nested
classes. It is used to group the classes logically and to achieve encapsulation. The outer
class members (including private) can be accessed by the inner class. The general syntax
for declaring the nested class is as follows:
1. class OuterClass
2. {
3. //code
4. class NestedClass
5. {
6. //code
7. }
8. }

The nested classes are of two types:

1. Static Nested class: A class that is static and nested is called a static nested class. It
interacts with the instance member of its outer class. We can create an object of the static
nested class by using the following syntax:

1. OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

2. Non-static Nested Class: Non-static nested classes are called inner classes.

The general syntax for declaring the static nested class and inner class is as follows:

1. class OuterClass
2. {
3. ...
4. static class StaticNestedClass
5. {
6. ...
7. }
8. class InnerClass
9. {
10. ...
11. }
12. }

Let's understand the concept of inner class through a Java program.

InnerClassExample.java
1. public class InnerClassExample
2. {
3. public static void main(String[] args)
4. {
5. System.out.println("This is outer class.");
6. }
7. class InnerClass
8. {
9. public void printinner()
10. {
11. System.out.println("This is inner class.");
12. }
13. }
14. }

Types of Inner Classes

Java provides the two types of inner classes are as follows:

o Local Classes or Method Local Inner Class


o Anonymous Classes or Anonymous Inner Class

Local Inner Class

It is a type of inner class that is defined inside a block. Here block denotes a method body
(a group of statements enclosed between a pair of braces). Due to defining inside a block
it is also known as method local inner class. These are the non-static classes because they
can access the instance members of the block. We can define the local inner classes in the
body of a method. These classes must be instantiated in the block in which they are
defined.

When we compile a Java program (a program that contains an inner class), the compiler
generates the two class files namely Outer.class and Outer$1Inner.class. One for the
outer class and the other for the inner class that contains a reference to the outer class.

Let's understand the concept of a local inner class through a Java program.

OuterClass.java
1. public class OuterClass
2. {
3. private void getValue()
4. {
5. //if you are using Java 7 make the variable final
6. //if you are using Java 8 the code runs successfully
7. int sum = 20;
8. //declaring method local inner class
9. class InnerClass
10. {
11. public int divisor;
12. public int remainder;
13. public InnerClass()
14. {
15. divisor = 4;
16. remainder = sum%divisor;
17. }
18. private int getDivisor()
19. {
20. return divisor;
21. }
22. private int getRemainder()
23. {
24. return sum%divisor;
25. }
26. private int getQuotient()
27. {
28. System.out.println("We are inside the inner class");
29. return sum / divisor;
30. }
31. }
32. //creating an instance of inner class
33. InnerClass ic = new InnerClass();
34. System.out.println("Divisor = "+ ic.getDivisor());
35. System.out.println("Remainder = " + ic.getRemainder());
36. System.out.println("Quotient = " + ic.getQuotient());
37. }
38. public static void main(String[] args)
39. {
40. //creating an instance of outer class
41. OuterClass oc = new OuterClass();
42. oc.getValue();
43. }
44. }

Output:

Divisor = 4
Remainder = 0
We are inside the inner class
Quotient = 5

Anonymous Inner Class

It is a type of inner class that is the same as local classes but the only difference is that the
class has not a class name and a single object is created of the class. It makes the code
more concise. It is used if we want to use the local class once. We can create anonymous
classes in the following two ways:

o By using an interface
o By declaring the class concrete and abstract

Syntax:

1. // the class may an interface, abstract or concrete class


2. DemoClass obj = new DemoClass()
3. {
4. //methods
5. //data members
6. public void demomethod()
7. {
8. //statements
9. }
10. };

Looking at the above syntax, we see that it is the same as the invocation of constructor
except that the class has a definition contained in the block.

AnonymousClassExample.java

1. interface Score
2. {
3. int run = 321;
4. void getScore();
5. }
6. public class AnonymousClassExample
7. {
8. public static void main(String[] args)
9. {
10. // Myclass is hidden inner class of Score interface
11. // whose name is not written but an object to it
12. // is created.
13. Score s = new Score()
14. {
15. @Override
16. public void getScore()
17. {
18. //prints score
19. System.out.print("Score is "+run);
20. }
21. };
22. s.getScore();
23. }
24. }

Output:

Score is 321
Java also provides another type of Java class is known as wrapper class. Let's discuss it in
detail.

Wrapper Class

In Java, the term wrapper class represents a collection of Java classes that objectify the
primitive type of Java. It means that for each primitive type there is a corresponding
wrapper class. The wrapper classes are used to perform the conversion from a primitive
type to an object and vice-versa. The following figure demonstrates the wrapper class
hierarchy.

The following table represents the primitive type and corresponding wrapper class.

Primitive Type Wrapper Class

boolean Boolean

int Integer

char Character

double Double
float Float

long Long

byte Byte

short Short

Let's understand the wrapper class through a Java program.

WrapperClassExample.java

1. public class WrapperClassExample


2. {
3. public static void main(String args[])
4. {
5. byte x = 0;
6. //wrapping byte primitive type into Byte object
7. Byte byteobj = new Byte(x);
8. int y = 23;
9. //wrapping int primitive type into Integer object
10. Integer intobj = new Integer(y);
11. char c='m';
12. //wrapping char primitive type into Character object
13. Character charobj=c;
14. //printing values from objects
15. System.out.println("Byte object byteobj: " + byteobj);
16. System.out.println("Integer object intobj: " + intobj);
17. System.out.println("Character object charobj: " + charobj);
18. }
19. }

Output:

Byte object byteobj: 0


Integer object intobj: 23
Character object charobj: m
Marker Interface in Java
In this section, we will discuss about marker interface in Java, its uses, built-in
(Serializable, Cloneable, and Remote Interfaces) and custom marker interface with
examples.

What is marker interface?


An interface that does not contain methods, fields, and constants is known as marker
interface. In other words, an empty interface is known as marker interface or tag
interface. It delivers the run-time type information about an object. It is the reason that
the JVM and compiler have additional information about an object.
The Serializable and Cloneable interfaces are the example of marker interface. In short,
it indicates a signal or command to the JVM.

The declaration of marker interface is the same as interface in Java but the interface
must be empty. For example:

1. public interface Serializable


2. {
3.
4. }

There are the two alternatives of marker interface that produces the same result as the
marker interface.

o Internal Flags: It can be used in place of marker interface to indicate any specific
operation.
o Annotations: Since Java 5, marker interfaces are omitted. Instead of marker
interface, Java 5 provides the annotations to achieve the same results. It allows
flexible metadata capability. Therefore, by applying annotations to any class, we
can perform specific action.

Uses of Marker Interface


Marker interface is used as a tag that inform the Java compiler by a message so that it
can add some special behavior to the class implementing it. Java marker interface are
useful if we have information about the class and that information never changes, in
such cases, we use marker interface represent to represent the same. Implementing an
empty interface tells the compiler to do some operations.

It is used to logically divide the code and a good way to categorize code. It is more
useful for developing API and in frameworks like Spring.

Built-in Marker Interface


In Java, built-in marker interfaces are the interfaces that are already present in
the JDK and ready to use. There are many built-in marker interfaces some of them are:

o Cloneable Interface
o Serializable Interface
o Remote Interface

Let's discuss one by one in detail.

Cloneable Interface
Cleanable interface in Java is also a marker interface that belong to java.lang package.
It generates replica (copy) of an object with different name. We can implement the
interface in the class of which class object to be cloned. It indicates the clone() method
of the Object class. If we do not implement the Cloneable interface in the class and
invokes the clone() method, it throws the ClassNotSupportedException.

Note that a class that implements the Cloneable interface must override the clone()
method with a public method. Let's see an example.

ADVERTISEMENT
Product.java

1. import java.util.Scanner;
2. public class Product implements Cloneable
3. {
4. int pid;
5. String pname;
6. double pcost;
7. //Product class constructor
8. public Product (int pid, String pname, double pcost)
9. {
10. this.pid = pid;
11. this.pname = pname;
12. this.pcost = pcost;
13. }
14. //method that prints the detail on the console
15. public void showDetail()
16. {
17. System.out.println("Product ID: "+pid);
18. System.out.println("Product Name: "+pname);
19. System.out.println("Product Cost: "+pcost);
20. }
21. public static void main (String args[]) throws CloneNotSupportedException
22. {
23. //reading values of the product from the user
24. Scanner sc = new Scanner(System.in);
25. System.out.print("Enter product ID: ");
26. int pid = sc.nextInt();
27. System.out.print("Enter product name: ");
28. String pname = sc.next();
29. System.out.print("Enter product Cost: ");
30. double pcost = sc.nextDouble();
31. System.out.println("-------Product Detail--------");
32. Product p1 = new Product(pid, pname, pcost);
33. //cloning the object of the Product class using the clone() method
34. Product p2 = (Product) p1.clone();
35. //invoking the method to print detail
36. p2.showDetail();
37. }
38. }

Output:

Enter product ID: 139872


Enter product name: Printer
Enter product Cost: 3459.67
-------Product Detail--------
Product ID: 139872
Product Name: Printer
Product Cost: 3459.67

Serializable Interface
It is a marker interface in Java that is defined in the java.io package. If we want to make
the class serializable, we must implement the Serializable interface. If a class
implements the Serializable interface, we can serialize or deserialize the state of an
object of that class.

Serialization (converting an object into byte stream) is a mechanism in which object


state is read from the memory and written into a file or database. Deserialization
(converting byte stream into an object) is the opposite of serialization means
that object state reading from a file or database and written back into memory is
called deserialization of object.
Serialization (writing) can be achieved with the ObjectOutputStream class and
deserialization (reading) can be achieved with the ObjectInputStream class.

Let's see example of serialization and deserialization.

Example of Serialization

Employee.java

1. import java.io.Serializable;
2. public class Employee implements Serializable
3. {
4. int empid;
5. String empname;
6. public Employee(int empid, String empname)
7. {
8. this.empid = empid;
9. this.empname = empname;
10. }
11. }

SerializationExample.java
1. import java.io.*;
2. class SerializationExample
3. {
4. public static void main(String args[])
5. {
6. try
7. {
8. //Creating the object
9. Employee emp =new Employee(1187345,"Andrew");
10. //Creating stream and writing the object
11. FileOutputStream fout=new FileOutputStream("employee data.txt");
12. ObjectOutputStream out=new ObjectOutputStream(fout);
13. out.writeObject(emp);
14. out.flush();
15. //closing the stream
16. out.close();
17. System.out.println("Data has been read from the file.");
18. }
19. catch(Exception e)
20. {
21. e.printStackTrace();
22. }
23. }
24. }

Output:

Data has been read from the file.

Example of Deserialization

Let's deserialize the object state.

ADVERTISEMENT

DeserializationExample.java
1. import java.io.*;
2. class DeserializationExample
3. {
4. public static void main(String args[])
5. {
6. try
7. {
8. //Creating stream to read the object
9. ObjectInputStream in=new ObjectInputStream(new FileInputStream("employee data.txt
"));
10. Employee emp=(Employee)in.readObject();
11. //printing the data of the serialized object
12. System.out.println(emp.empid+" "+emp.empname);
13. //closing the stream
14. in.close();
15. }
16. catch(Exception e)
17. {
18. e.printStackTrace();
19. }
20. }
21. }

Output:

1187345 Andrew

Remote Interface
ADVERTISEMENT
ADVERTISEMENT

Remote interface is a marker interface that belong to java.rmi package. It marks an


object as remote that can be accessed from another machine (host). We must
implement the Remote interface if we want to make an object as remote. It identifies the
interfaces whose methods can be invoked from a non-local JVM. Any remote object
must implement the interface directly or indirectly.
Let's define a Remote interface and implement it in a Java program.

Defining Remote interface

1. import java.rmi.*;
2. public interface AddAll extends Remote
3. {
4. public int add(int r, int s)throws RemoteException;
5. }

Implement the Remote Interface

There are following two ways to implement the Remote interface:

o By extending the UnicastRemoteObject class


o By using the exportObject() method of the UnicastRemoteObject class

AddAllRemote.java

1. import java.rmi.*;
2. import java.rmi.server.*;
3. public class AddAllRemote extends UnicastRemoteObject implements Adder
4. {
5. AddAllRemote()throws RemoteException
6. {
7. super();
8. }
9. public int add(int r, int s)
10. {
11. return r+s;
12. }

Create and Start the Remote Application

Server.java

1. import java.rmi.*;
2. import java.rmi.registry.*;
3. public class Server
4. {
5. public static void main(String args[])
6. {
7. try
8. {
9. AddAll stub=new AddAllRemote();
10. Naming.rebind("rmi://localhost:5000/sak",stub);
11. }
12. catch(Exception e)
13. {
14. System.out.println(e);
15. }
16. }
17. }

Create and Start the Client Application

Client.java

1. import java.rmi.*;
2. public class Client
3. {
4. public static void main(String args[])
5. {
6. try
7. {
8. AddAll stub=(AddAll)Naming.lookup("rmi://localhost:5000/sak");
9. System.out.println(stub.add(29,18));
10. }
11. catch(Exception e)
12. {
13. }
14. }
15. }

Custom Marker Interface


Apart from built-in marker interface, Java also allows us to create own marker interface.
Let's see an example.

CustomMarkerInterfaceExample.java

1. //custom marker interface


2. interface Car
3. {
4.
5. }
6. //custom marker interface
7. interface Engine
8. {
9.
10. }
11. //class that implements the Car marker interface
12. class Vehicle implements Car
13. {
14. static void isVehicle()
15. {
16. System.out.println("Car is a vehicle.");
17. }
18. }
19. //class that implements the Engine marker interface
20. class Status implements Engine
21. {
22. static void isWorking()
23. {
24. System.out.println("Yes, engine is working.");
25. }
26. }
27. //main class
28. public class CustomMarkerInterfaceExample
29. {
30. public static void main(String args[])
31. {
32. //invoking the methods of the class
33. Vehicle.isVehicle();
34. Status.isWorking();
35. }
36. }

Output:

Car is a vehicle.
Yes, engine is working.

What is token in Java?


The Java compiler breaks the line of code into text (words) is called Java tokens. These
are the smallest element of the Java program. The Java compiler identified these words
as tokens. These tokens are separated by the delimiters. It is useful for compilers to
detect errors. Remember that the delimiters are not part of the Java tokens.

1. token <= identifier | keyword | separator | operator | literal | comment


For example, consider the following code.

1. public class Demo


2. {
3. public static void main(String args[])
4. {
5. System.out.println("javatpoint");
6. }
7. }

In the above code snippet, public, class, Demo, {, static, void, main, (, String, args,
[, ], ), System, ., out, println, javatpoint, etc. are the Java tokens.
The Java compiler translates these tokens into Java bytecode. Further, these bytecodes
are executed inside the interpreted Java environment.

Types of Tokens
Java token includes the following:

ADVERTISEMENT

ADVERTISEMENT

o Keywords
o Identifiers
o Literals
o Operators
o Separators
o Comments

Keywords: These are the pre-defined reserved words of any programming language.
Each keyword has a special meaning. It is always written in lower case. Java provides the
following keywords:

01. abstract 02. boolean 03. byte 04. break 05. clas

06. case 07. catch 08. char 09. continue 10. def

11. do 12. double 13. else 14. extends 15. fina

16. finally 17. float 18. for 19. if 20. imp

21. import 22. instanceof 23. int 24. interface 25. lon

26. native 27. new 28. package 29. private 30. pro
31. public 32. return 33. short 34. static 35. sup

36. switch 37. synchronized 38. this 39. thro 40. thro

41. transient 42. try 43. void 44. volatile 45. whi

46. assert 47. const 48. enum 49. goto 50. stri

Identifier: Identifiers are used to name a variable, constant, function, class, and array. It
usually defined by the user. It uses letters, underscores, or a dollar sign as the first
character. The label is also known as a special kind of identifier that is used in the goto
statement. Remember that the identifier name must be different from the reserved
keywords. There are some rules to declare identifiers are:

o The first letter of an identifier must be a letter, underscore or a dollar sign. It cannot start
with digits but may contain digits.
o The whitespace cannot be included in the identifier.
o Identifiers are case sensitive.

Some valid identifiers are:

1. PhoneNumber
2. PRICE
3. radius
4. a
5. a1
6. _phonenumber
7. $circumference
8. jagged_array
9. 12radius //invalid

Literals: In programming literal is a notation that represents a fixed value (constant) in


the source code. It can be categorized as an integer literal, string literal, Boolean literal,
etc. It is defined by the programmer. Once it has been defined cannot be changed. Java
provides five types of literals are as follows:
o Integer
o Floating Point
o Character
o String
o Boolean

Literal Type

23 int

9.86 double

false, true boolean

'K', '7', '-' char

"javatpoint" String

null any reference type

Operators: In programming, operators are the special symbol that tells the compiler to
perform a special operation. Java provides different types of operators that can be
classified according to the functionality they provide. There are eight types of operators
in Java, are as follows:

o Arithmetic Operators
o Assignment Operators
o Relational Operators
o Unary Operators
o Logical Operators
o Ternary Operators
o Bitwise Operators
o Shift Operators

Operator Symbols

Arithmetic +,-,/,*,%

Unary ++ , - - , !

Assignment = , += , -= , *= , /= , %= , ^=

Relational ==, != , < , >, <= , >=

Logical && , ||

Ternary (Condition) ? (Statement1) : (Statement2);

Bitwise &,|,^,~

Shift << , >> , >>>

Separators: The separators in Java is also known as punctuators. There are nine
separators in Java, are as follows:

1. separator <= ; | , | . | ( | ) | { | } | [ | ]

Note that the first three separators (; , and .) are tokens that separate other tokens, and the
last six (3 pairs of braces) separators are also known as delimiters. For example,
Math.pow(9, 3); contains nine tokens.

o Square Brackets []: It is used to define array elements. A pair of square brackets
represents the single-dimensional array, two pairs of square brackets represent the two-
dimensional array.
o Parentheses (): It is used to call the functions and parsing the parameters.
o Curly Braces {}: The curly braces denote the starting and ending of a code block.
o Comma (,): It is used to separate two values, statements, and parameters.
o Assignment Operator (=): It is used to assign a variable and constant.
o Semicolon (;): It is the symbol that can be found at end of the statements. It separates
the two statements.
o Period (.): It separates the package name form the sub-packages and class. It also
separates a variable or method from a reference variable.

Comments: Comments allow us to specify information about the program inside our
Java code. Java compiler recognizes these comments as tokens but excludes it form
further processing. The Java compiler treats comments as whitespaces. Java provides the
following two types of comments:

o Line Oriented: It begins with a pair of forwarding slashes (//).


o Block-Oriented: It begins with /* and continues until it founds */.

Java Xmx
In this section, we will understand what is Xmx in Java, how to set up maximum heap
size for the Java application.

In Java, sometimes when we run the Java application it shows an error message like the
following:

Error occurred during initialization of VM. Could not reserve enough space for object heap.
Could not create the Java virtual machine.

The above error indicates that increases the heap size for running the application. There
is no sufficient space for creating the object. The solution to this error is to increase the
heap size by using the Java -Xmx argument along with the specified heap size. Let's
see what is -Xmx in Java.

What is Xmx in Java?


In Java, Xmx is a flag that specifies the maximum memory (in bytes) allocation pool for
the JVM. It sets up the maximum heap size. Remember that the value must be in
multiples of 1024 and must be greater than 2MB. It uses the letter K or k to represents
the size in kilobytes, and the letter M and m to represent the size in megabytes. The
default heap size is 64M.

Default Heap Size


The default initial maximum heap size is based on the ergonomics algorithm. In Java,
the initial heap size is 256M or 266634176 bytes and the maximum heap size
is 4068M or 4266146816 bytes.

We recommend you to set the maximum heap size between 512M to 1024M for small
and medium Java application.

1. java -Xms512M -Xmx1024M

Setting up Maximum Heap Size


We can increase the heap size to any value that we want but remember that RAM must
support that value. Suppose, we want to set the maximum heap size to 80M. We can use
any of the following flags for setting up the maximum heap size. All the commands
allocate the same heap size.

1. -Xmx83886080 (memory allocation in bytes)


2. -Xmx81920k (memory allocation in kilobytes)
3. -Xmx80M (memory allocation in Megabytes)

The above Xmx flags allocate the Java heap memory to a maximum size of 80MB. Note
that there is no space between the flag (-Xmx) and memory size (80M). It does not
matter if you are using an uppercase or lower-case letter. For example, -Xmx80M is the
same as -Xmx80m. It means that the application can use the maximum heap size of
80M of the available memory. Therefore, the -Xmx flag in Java, changes the maximum
heap size for the JVM.

Follow the steps given below for setting up the maximum heap size.

Step 1: Open the Control Panel and click on the System icon.

ADVERTISEMENT
Step 2: Click on the Advanced system settings. It opens the System Properties
window.

Step 3: In the System Properties window, click on the Environment Variables. It opens
the Environment Variables dialog box.
Step 4: In the Environment Variables dialog box, click on the New button presented
under the System Variables.
Step 5: In the window, provide the Variable name _JAVA_OPTIONS and Variable value -
Xmx512m. You can put any value in place of 512. After that, click on the OK button
three times.

Now, we have set the maximum heap size 512M.

If you are using Eclipse IDE, the same this can be done by specifying the VM arguments,
as we have shown below.
Why do we need to maximize the heap size?
If the Java process has exceeded the -Xmx maximum Java heap size, the
popular java.lang.OutOfMemoryError will be thrown.

ADVERTISEMENT

Other Command-line Arguments Related to


Memory
Java provides more options for controlling the Java application memory. If we want to
see which options are available for memory, we can use the java -X command. It shows
the different options available for handling the memory.
In the above result, there are four command-line arguments related to Java application
memory.

ADVERTISEMENT
ADVERTISEMENT

o -Xnoclassgc: Disable class garbage collection.


o -Xms<size>: The command sets the initial size of the Java heap. Its default size is
2M (2097152 bytes). The size should be greater than 1024 byte (1KB). It must be
the multiple of 1024.
o -Xmx<size>: Set maximum Java heap size.
o -Xss<size>: Set Java thread stack size.
Examples
Let's see some examples based on Xmx.

o -Xms2m -Xmx80m: Heap starts growing from 2MB to 80MB.


o -Xms70m -Xmx70m: Heap starts at 70 MB and it will never grow.
o -Xms40m: Heap starts at 40 MB and grows to the default maximum size.
o -Xmx256m: Heap starts at default initial value and grows to a maximum of 256
MB
How to Enable Java in Chrome
The Java plugin is part of the Java Runtime Environment (JRE). It allows a browser to work with
the Java platform to run Java applets. Almost all the browsers enable Java plugin but sometimes
we get the error like the Chrome does not support Java. To overcome this problem, we
need to enable Java in chrome. In this section, we will learn how to enable Java in
Chrome.

If you are using the latest version of Google Chrome Browser, the web pages with embedded
Java applets no longer work. By enabling Java in Chrome, we can resolve this problem.

The Java plugin is enabled in a large number of browsers and this makes it a target for malicious
hackers. Any third-party plugin can be subjected to the same kind of unwanted attention. The
team who developed Java has always taken security seriously. They always work for quickly
release an update to patch any serious security. It means that the best way to diminish problems
with the Java plugin is to make sure it is up-to-date with the latest release.

Reason to Enable Java in Chrome


Even after installing Java, when we try to run Applets they do not run because the browser we
use is not Java-enabled. It is the reason the browser must be Java-enabled. The question arises
that why we need to enable Java in Chrome.

When we load a website or a web service in which Java technology is used, shows a
message, the Chrome browser does not support Java.

The reason is that the Chrome browser no longer supports the NPAPI. NPAPI is a technology
that supports Java applets.

The Java plugin for web browsers depends on the cross-platform plugin architecture NPAPI.
Over a decade, it had been supported by all the major web browsers. The Google Chrome
version 45 and above versions have dropped support for NPAPI. Therefore, Java plugin does not
work for the browsers.

Java applications are offered as either a web start application or as a Java applet. This change
does not affect Web Start applications it only impacts applets. Developers and System
administrators looking for alternative ways to support users of chrome.

Solution to the Problem


If we have already installed Java, we need to restart the browser in order to enable Java. The
process recognizes the installation of Java. Make sure that Java content in the browser is enabled
through the Java Control Panel.

Alternatively, if we are using a website that uses Java, in this case, we must opt for the enable or
disable the Java plugin, as required.

There is an alternative way to enable Java in Chrome by using the IE Tab extension.

Using IE Tab Extension


Step 1: Go to Chrome Web Store.

Step 2: Type IE Tab in the search box.

Step 3: Click on the IE Tab Extension.

Step 4: Click on the Add to Chrome button.


Step 5: Click on the Add extension button.

It adds the IE Tab Extension to the Chrome that displays at the right side of the address bar.

Step 6: Click on the IE Tab icon. It downloads the ietabhelper.exe file. After downloading
the .exe file, double-click on the file. It shows a dialog box that asks to Run or Cancel the
execution of the file.
After clicking on the Run button, it opens the following page in the Chrome browser.

Now, we have resolved the problem. Each time when we visit a web page that contains
Java content and the page is unable to open because of Java is not enabled. To display
the web page, click on the IE Tab icon presented in the top-right corner of the browser.
It opens a new IE Tab and uses the Internet Explorer engine along with the support of
Java.
Java Semaphore
In Java, we use semaphore in the thread synchronization. It is used to control access to
a shared resource that uses a counter variable. Java also provides a Semaphore
class that contains constructors and various methods to control access over the shared
resource. We will discuss it later in this section.

Before moving ahead in this section, first, we will understand what is semaphore, types
of semaphore, how it works, and how to implement semaphore. After knowing all
about it, we will move to the Java semaphore programs.

What is a semaphore?
A Semaphore is used to limit the number of threads that want to access a shared
resource. In other words, it is a non-negative variable that is shared among the threads
known as a counter. It sets the limit of the threads. A mechanism in which a thread is
waiting on a semaphore can be signaled by other threads.

o If counter > 0, access to shared resources is provided.


o If counter = 0, access to shared resources is denied.

In short, the counter keeps tracking the number of permissions it has given to a shared
resource. Therefore, semaphore grants permission to threads to share a resource.

Characteristics of Semaphore
There are the following characteristics of a semaphore:

o It provides synchronization among the threads.


o It decreases the level of synchronization. Hence, provides a low-level
synchronization mechanism.
o The semaphore does not contain a negative value. It holds a value that may
either greater than zero or equal to zero.
o We can implement semaphore using the test operation and interrupts, and we
use the file descriptors for executing it.

Working of Semaphore
Semaphore controls over the shared resource through a counter variable. The counter is
a non-negative value. It contains a value either greater than 0 or equal to 0.

o If counter > 0, the thread gets permission to access the shared resource and the
counter value is decremented by 1.
o Else, the thread will be blocked until a permit can be acquired.
o When the execution of the thread is completed then there is no need for the
resource and the thread releases it. After releasing the resource, the counter
value incremented by 1.
o If another thread is waiting for acquiring a resource, the thread will acquire a
permit at that time.
o If counter = 0, the thread does not get permission to access the shared resource.

Let's understand the working of semaphore with the help of a flow chart.
Types of Semaphores
There are four types of semaphores, which are as follows:

o Counting Semaphores
o Bounded Semaphores
o Timed Semaphores
o Binary Semaphores
Let's discuss one by one in detail.

Counting Semaphores
The counting semaphores are used to resolve the situation in which more than one
process wants to execute in the critical section, simultaneously. Hence to overcome this
problem we use counting semaphore. For example, consider the following code snippet.

Let's see the implementation of the counting semaphores.

CountingSemaphoresExample.java

1. public class CountingSemaphoreExample


2. {
3. private int signal = 0;
4. public synchronized void take()
5. {
6. this.signal++;
7. this.notify();
8. }
9. public synchronized void release() throws InterruptedException
10. {
11. while(this.signal == 0)
12. wait();
13. this.signal--;
14. }
15. }

Bounded Semaphores
We can set the upper bound limit using the bounded semaphores. It is used in place of
the counting semaphores because the counting semaphores do not contain any upper
bound value. The upper bound value denotes how many signals it can store. For
example, consider the following code snippet.

Let's see the implementation of the bounded semaphore.

BoundedSemaphoresExample.java

1. public class BoundedSemaphoresExample


2. {
3. private int signals = 0;
4. private int bound = 0;
5. public BoundedSemaphoreexample(int upperBound)
6. {
7. this.bound = upperBound;
8. }
9. public void synchronized take() throws InterruptedException
10. {
11. while(this.signals == bound)
12. wait();
13. this.signals++;
14. this.notify++;
15. }
16. public void synchronized release() throws InterruptedException
17. {
18. while(this.signal == 0)
19. wait();
20. this.signals--;
21. }
22. }

Timed Semaphores
The timed semaphores allow a thread to run for a specified period of time. After a
particular time, the timer resets and releases all other permits.

Let's see the implementation of the timed semaphores.

TimedSemaphoresExample.java

1. class TimedSemaphoresExample
2. {
3. private TimedSemaphore semaphore;
4. TimedSemaphoreExample(long period, int slotLimit)
5. {
6. semaphore = new TimedSemaphore(period, TimeUnit.SECONDS, slotLimit);
7. }
8. boolean tryAdd()
9. {
10. return semaphore.tryAcquire();
11. }
12. int availableSlots()
13. {
14. return semaphore.getAvailablePermits();
15. }
16. }
Binary Semaphores
The binary semaphores are the same as counting semaphores. But remember that it
accepts only binary values either 0 or 1. Its implementation is easy in comparison to
other semaphores. If the value is 1, the signal operation is success, fails otherwise.

Let's see the implementation of binary semaphores.

ADVERTISEMENT

BinarySemaphoresExample.java

1. public class BinarySemaphoreExample


2. {
3. private boolean locked = false;
4. BinarySemaphore(int initial)
5. {
6. locked = (initial == 0);
7. }
8. public synchronized void waitForNotify() throws InterruptedException
9. {
10. while (locked)
11. {
12. wait();
13. }
14. locked = true;
15. }
16. public synchronized void notifyToWakeup()
17. {
18. if (locked)
19. {
20. notify();
21. }
22. locked = false;
23. }
24. }
Semaphore in Java
In Java, it is a thread synchronization construct. The construct uses a variable known
as a counter that controls access over the shared resource. It is a type of variable which
is used to manage concurrent processes and also synchronize them. It is also used to
avoid race conditions. It restricts the number of threads to access a shared resource.

ADVERTISEMENT
ADVERTISEMENT

For example, we can restrict a file to access up to 10 connections simultaneously.

Java Semaphore Class


Java provides a Semaphore class to implement the semaphore mechanism. It belongs
to the java.util.concurrent package. It implements the Serializable interface. Hence,
manual implementation is not required.

The Semaphore class provides the following two constructors:

o Semaphore(int permits)
o Semaphore(int permits, boolean fair)

Semaphore(int permits)

It creates a Semaphore and parses the number of permits (initial number of permits
available) as an argument. It specifies the number of threads that can share a resource at
a time. The value of permits may be negative. In such a case, a release must occur
before any acquires will be granted.

Syntax:

1. public Semaphore(int permits)

Semaphore(int permits, boolean fair)

It creates a Semaphore with the given number of permits and the given fairness settings.

ADVERTISEMENT

Syntax:
1. public Semaphore(int permits, boolean fair)

It parses two parameters:

o permits: The value of permits may be negative. In such a case, the release must
occur before any acquires will be granted.
o fair: If we set the value to true, the semaphore guarantees FIFO to the threads in
the order they are requested, false By default, all the threads that are waiting for
the resource grants permit in an undefined order.

Methods of the Semaphore Class


The class provides the following methods:

acquire() Method: The method acquire the permits from the semaphore, blocking until
one is available, or the thread is interrupted. It reduces the number of available permits
by 1.

If there is no permit is available for the current thread, the thread becomes disabled for
the thread scheduling purposes. The current thread goes in the inactive state until one
of two things happens:

o If the other thread invokes the release() method to release the resource then the
current thread gets permits.
o If the other thread interrupts the current thread.

It throws InterruptedException if the current thread is interrupted. The method does


not return any value.

Syntax:

1. public void acquire() throws InterruptedException

release() Method: It releases a permit and returns it to the semaphore. It increments


the number of available permits by 1. If a thread tries to acquire a permit, the
semaphore grants permission to acquire the resource that was just released by other
threads. Further, that thread is considered for thread scheduling purposes.

Syntax:
1. public void release()

availablePermits() Method: The method returns the number of permits available in


semaphore for granting the resource. Usually, it is used for debugging and testing
purposes.

Syntax:

1. public int availablePermits()

Let's understand the above methods through a simple example.

1. Semaphore semaphore = new Semaphore(6); //creates a semaphore with 6 permits


2. semaphore.acquire(); //acquire 1 ticket
3. semaphore.availablePermits(); //current available permits is 5
4. semaphore.release(); //releases the acquire ticket and increments the permit by 1
5. semaphore.availablePermits(); //current available permits is 5

Using Semaphore as Lock


Java allows us to use a semaphore as a lock. It means, it locks the access to the resource.
Any thread that wants to access the locked resource, must call the acquire() method
before accessing the resource to acquire the lock. The thread must release the lock by
calling the release() method, after the completion of the task. Remember that set the
upper bound to 1. For example, consider the following code snippet:

ADVERTISEMENT

1. Semaphore sem= new Semaphore(1);


2. ...
3. sem.acquire();
4. try
5. {
6. //critical section
7. }
8. finally
9. {
10. sem.release();
11. }

Let's see an example of a semaphore and use semaphore as a lock.

SemaphoreAsLock.java

1. import java.util.concurrent.*;
2. //a shared resource or class.
3. class Shared
4. {
5. static int count = 0;
6. }
7. class DemoThread extends Thread
8. {
9. //object of the Semaphore class
10. Semaphore semaphore;
11. //variable for storing the thread name
12. String threadName;
13. public DemoThread(Semaphore semaphore, String threadName)
14. {
15. super(threadName);
16. this.semaphore = semaphore;
17. this.threadName = threadName;
18. }
19. @Override
20. public void run()
21. {
22. // run by thread A
23. if(this.getName().equals("A"))
24. {
25. System.out.println("Starting thread " + threadName);
26. try
27. {
28. // First, get a permit.
29. System.out.println(threadName + " is waiting for a permit.");
30. //acquiring the lock
31. semaphore.acquire();
32. System.out.println(threadName + " gets a permit.");
33. //current thread A is accessing the resource and the
34. //other threads are waiting for to get the resource
35. //until the thread A release the lock
36. for(int i=0; i < 5; i++)
37. {
38. //thread A has acquired the resource
39. //hence the value of the count is incremented to 1
40. Shared.count++;
41. System.out.println(threadName + ": " + Shared.count);
42. //now, allowing a context switch for thread B to execute
43. //sleeps thread for 1 second
44. Thread.sleep(1000);
45. }
46. }
47. catch (InterruptedException e)
48. {
49. e.printStackTrace();
50. }
51. //release the permit
52. System.out.println("Thread " +threadName + " releases the permit.");
53. semaphore.release();
54. }
55. // run by thread B
56. else
57. {
58. System.out.println("Starting thread " + threadName);
59. try
60. {
61. //first, get a permit
62. System.out.println("Thread " +threadName + " is waiting for a permit.");
63. //acquiring the lock
64. semaphore.acquire();
65. System.out.println("Thread " +threadName + " gets a permit.");
66. //Now, accessing the shared resource.
67. //other waiting threads will wait, until this
68. //thread release the lock
69. for(int i=0; i < 5; i++)
70. {
71. //decrements the count value
72. Shared.count--;
73. System.out.println(threadName + ": " + Shared.count);
74. //Now, allowing a context switch -- if possible.
75. //for thread A to execute
76. //sleeps thread for 1 second
77. Thread.sleep(1000);
78. }
79. }
80. catch (InterruptedException e)
81. {
82. e.printStackTrace();
83. }
84. //release the permit
85. System.out.println("Thread " +threadName + " releases the permit.");
86. //release the resource
87. semaphore.release();
88. }
89. }
90. }
91. //creating driver class
92. public class SemaphoreAsLock
93. {
94. public static void main(String args[]) throws InterruptedException
95. {
96. //creating the constructor of the Semaphore with initial permit 1
97. Semaphore semaphore = new Semaphore(1);
98. //creating two threads with the name A and B
99. //thread A increments the count value
100. //while the thread B decrements the count value
101. DemoThread dt1 = new DemoThread(semaphore, "A");
102. DemoThread dt2 = new DemoThread(semaphore, "B");
103. //stating both threads A and B
104. dt1.start();
105. dt2.start();
106. //waiting for thread A
107. dt1.join();
108. //waiting for thread B
109. dt2.join();
110. //after completing the execution of the threads, the count value will be 0 always
111. System.out.println("count: " + Shared.count);
112. }
113. }

Output:
Note: When we execute the above program, we get different output every time. So, your
output may differ from the output shown above.

Java Semaphore Example


Let's understand the semaphore mechanism through a Java program. In the following
example, we have created a constructor of the Semaphore class with the initial permit
value 3.

SemaphoreExample.java

1. import java.util.concurrent.Semaphore;
2. public class SemaphoreExample
3. {
4. //creating constructor of the Semaphore with the initial value 3
5. static Semaphore semaphore = new Semaphore(3);
6. static class DemoThread extends Thread
7. {
8. String name = "";
9. //constructor of the DemoThread class
10. DemoThread(String name)
11. {
12. this.name = name;
13. }
14. public void run()
15. {
16. try
17. {
18. System.out.println("Thread "+name + " : acquiring lock...");
19. System.out.println("Thread "+name + " : available Semaphore permits is: "+ semaphore.
availablePermits());
20. //thread A acquire lock and the permit count decremented by 1
21. semaphore.acquire();
22. System.out.println("Thread "+name + " : got the permit!");
23. try
24. {
25. for (int i = 1; i <= 5; i++)
26. {
27. System.out.println("Thread "+name + " : is performing operation " + i+ ", available Sema
phore permits : "+ semaphore.availablePermits());
28. //sleep 2 second
29. Thread.sleep(2000);
30. }
31. }
32. finally
33. {
34. System.out.println("Thread "+name + " : releasing lock...");
35. //invoking release() method after successful execution
36. semaphore.release();
37. //prints the total number of available permits
38. System.out.println("Thread "+name + " : available Semaphore permits is: "+ semaphore.
availablePermits());
39. }
40. }
41. catch (InterruptedException e)
42. {
43. e.printStackTrace();
44. }
45. }
46. }
47. //main method
48. public static void main(String[] args)
49. {
50. //prints the total number of available permits
51. System.out.println("Total available Semaphore permits is: "+ semaphore.availablePermits
());
52. //creating four threads namely A, B, C, and D
53. DemoThread t1 = new DemoThread("A");
54. //staring thread A
55. t1.start();
56. DemoThread t2 = new DemoThread("B");
57. //staring thread B
58. t2.start();
59. DemoThread t3 = new DemoThread("C");
60. //staring thread C
61. t3.start();
62. DemoThread t4 = new DemoThread("D");
63. //staring thread D
64. t4.start();
65. }
66. }
Output:
Java Array to List
In Java, Array and List are the two most important data structures. In this section, we
will learn how to convert Java Array into a List. We have also created Java
programs that convert Array into a List by using different Java methods.

Converting Array to List in Java


Java array is a collection of multiple values of the same data type. An array can contain
objects and primitive types. It depends on the definition of the array. If an array
definition is of primitive type, the values of the array store in the contagious memory
location. If an array contains objects elements, elements stored in the heap segment.

In Java, a List is an interface that belongs to the Java Collections framework. It stores
elements in the form of objects in an ordered manner and preserves the insertion order.
It allows us to store duplicate values. The
classes ArrayList, LinkedList, Vector and Stack implements the List interface.

Java provides five methods to convert Array into a List are as follows:

Backward Skip 10sPlay VideoForward Skip 10s

o Native Method
o Using Arrays.asList() Method
o Using Collections.addAll() Method
o Using Java 8 Stream API
o Using Guava Lists.newArrayList() Method

Native Method
It is the simplest method to convert Java Array into a List. In this method first, we create
an empty List and add all the elements of the array into the List. Let's see an example.

ArrayToListExample1.java

1. import java.util.*;
2. public class ArrayToListExample1
3. {
4. public static void main(String args[])
5. {
6. //creating an array
7. String array[] = { "Golf", "Soccer", "Baseball", "Volleyball", "Tennis", "Badminton", "Rugby", "Arche
ry", "Skiing"};
8. //prints the array before conversion
9. System.out.println("Array before conversion: "+ Arrays.toString(array));
10. //calling the generic function that converts Array into List
11. List<String> list = ArrayToListConversion(array);
12. //print the List
13. System.out.println("Array as List: " + list);
14. }
15. //creating a generic function that converts the Array into List
16. public static <T> List<T> ArrayToListConversion(T array[])
17. {
18. //creating the constructor of the List class
19. List<T> list = new ArrayList<>();
20. //using for-each loop to iterate over the array
21. for (T t : array)
22. {
23. //adding each element to the List
24. list.add(t);
25. }
26. //returns the list converted into Array
27. return list;
28. }
29. }

Output:

Using Arrays.asList() Method


It is the method of the Java Arrays class that belongs to java.util package. When we use
the asList() method with the Collection.toArray() method, it works as a bridge between
array-based and collection-based APIs.

Syntax:

1. public static <T> List<T> asList(T... a)

The method parses an array as a parameter by which the list will be backed. It returns a
serializable fixed-size list view of the specified array. Let's see an example.

ArrayToListExample2.java

1. import java.util.*;
2. public class ArrayToListExample2
3. {
4. public static void main(String args[])
5. {
6. //creating an array to be converted
7. String arr[] = { "Aston Martin", "Bugatti", "Bentley", "Alfa Romeo", "Buick", "Acura", "Audi", "BMW
", "Buick" };
8. //prints array before conversion
9. System.out.println("Array before conversion: "+ Arrays.toString(arr));
10. //calling generic method that converts Array into List
11. List<String> list = ArrayToListConversion(arr);
12. //prints the List
13. System.out.println("Array after conversion: " + list);
14. }
15. //creating a generic function that converts the Array into List
16. public static <T> List<T> ArrayToListConversion(T arr[])
17. {
18. //invoking the asList() method and passing the array to be converted
19. List<T> list = Arrays.asList(arr);
20. //returns the list
21. return list;
22. }
23. }

Output:

Using Collections.addAll() Method


It is the method of the Java Collections class. it belongs to java.util package. The class
provides a method named addAll(). We can use the method to convert Array into a List.
It adds all the elements to the specified collection. We can specify elements either
individually or in the form of an array. It works the same
as c.addAll(Arrays.asList(elements)). It is a faster implementation than another
implementation.

Syntax:

1. public static <T> boolean addAll(Collection<? super T> c, T... elements)

It parses two parameters:

o c: It is a collection in which elements are to be added.


o elements: The elements are to be inserted into c.
It returns true if the collection changed as a result of the call. It throws the following
exceptions:

o If the parameter c does not support the add operation, it


throws UnsupportedOperationException.
o If the specified array elements contain one or more null values and c does not allow null
elements, it throws NullPointerException.
o If any array element prevents it from being added to the parameter c it
throws IllegalPointerException.

Let's see an example.

ArrayToListExample3.java

1. import java.util.*;
2. public class ArrayToListExample3
3. {
4. public static void main(String args[])
5. {
6. //creating an Array to be converted
7. String arr[] = { "San Jose", "Dallas", "Chicago","San Antonio", "Los Angeles", "Portland", "Tucson"
};
8. //prints the Array
9. System.out.println("Array before conversion: "+ Arrays.toString(arr));
10. //method calling
11. List<String> list = ArrayToListConversion(arr);
12. //print the List
13. System.out.println("Array after conversion: " + list);
14. }
15. //creating a generic function that converts the Array into List
16. public static <T> List<T> ArrayToListConversion(T arr[])
17. {
18. //creating the constructor of thr List class
19. List<T> list = new ArrayList<>();
20. //the method adds Array to the List
21. Collections.addAll(list, arr);
22. //returns the list
23. return list;
24. }
25. }

Output:

Using Java 8 Stream API


Java 8 provides the Stream API to process the collections of objects. It is a sequence of
methods that can be pipelined to produce the desired result. Remember that it does not
change the original data structure. It provides the output based on the pipelined
methods. We can attain Stream in a number of ways but in the following program, we
have used Arrays.stream(Object[]) to attain the stream.

Collectors.toList() Method: The method returns a Collector that collects the input
elements into a newly created List in an encounter method.

Syntax:

1. public static <T> Collector<T,?,List<T>> toList()


ADVERTISEMENT

ADVERTISEMENT

Where T is the type of element that we have specified. The method does not provide
guarantees on type, mutability, thread-safety, and serializability.

Let's use the Stream API in a Java program and convert an array into a List.

ArrayToListExample4.java

1. import java.util.*;
2. import java.util.stream.Collectors;
3. public class ArrayToListExample4
4. {
5. //creating a generic function that converts the Array into List
6. public static <T> List<T> ArrayToListConversion(T arr[])
7. {
8. //creates a list from the specified Array and returns the List
9. return Arrays.stream(arr).collect(Collectors.toList());
10. }
11. public static void main(String args[])
12. {
13. //creating an array to be converted into List
14. String arr[] = { "Python", "HTM", "Java", "C", "C++", "JavaScript", "Ruby", "Swift", "PHP" };
15. //prints the Array before conversion
16. System.out.println("Array: "+ Arrays.toString(arr));
17. //calling the method created above and storing the elements into the List object
18. List<String> list = ArrayToListConversion(arr);
19. //prints the List
20. System.out.println("List: " + list);
21. }
22. }

Output:

Using Guava Lists.newArrayList()


It is the method of the Lists class that belong to com.google.common.collect package.
The class provides a method newArrayList() that creates mutable empty ArrayList
instance having the elements of the specified array.

Syntax:

1. public static <E> ArrayList<E> newArrayList(E... elements)


Note: The newArrayList() method is available for Java 6 and earlier versions. In later
versions it is deprecated. Instead of the above method, we use ArrayList constructor
directly.

ArrayToListExample5.java

1. import static com.google.common.collect.Lists.*;


2. import java.util.*;
3. public class ArrayToListExample5
4. {
5. public static void main(String args[])
6. {
7. //creating an Array to be converted into a List
8. String arr[] = { "Mango", "Banana", "Grapes", "Apple", "Plum", "Blackberry", "Papaya", "Orange" }
;
9. //prints the Array before conversion
10. System.out.println("Array: "+ Arrays.toString(arr));
11. //convert the Array to List
12. List<String> list = ArrayToListConversion(arr);
13. //prints the List
14. System.out.println("List: " + list);
15. }
16. //creating a generic function that converts the Array into List
17. public static <T> List<T> ArrayToListConversion(T arr[])
18. {
19. //creates a List from the specified Array
20. return Lists.newArrayList(arr);
21. }
22. }

Output:
JIT in Java
When we write a program in any programming language it requires converting that code in the
machine-understandable form because the machine only understands the binary language.
According to the programming languages, compiler differs. The compiler is a program that
converts the high-level language to machine level code. The Java programming language uses
the compiler named javac. It converts the high-level language code into machine code
(bytecode). JIT is a part of the JVM that optimizes the performance of the application. JIT stands
for Java-In-Time Compiler. The JIT compilation is also known as dynamic compilation. In
this section, we will learn what is JIT in Java, its working, and the phases of the JIT
compiler.

What is JIT in Java?


JIT in Java is an integral part of the JVM. It accelerates execution performance many times over
the previous level. In other words, it is a long-running, computer-intensive program that provides
the best performance environment. It optimizes the performance of the Java application at
compile or run time.

The JIT compilation includes two approaches AOT (Ahead-of-Time compilation)


and interpretation to translate code into machine code. AOT compiler compiles the code into a
native machine language (the same as the normal compiler). It transforms the bytecode of a VM
into the machine code. The following optimizations are done by the JIT compilers:

ADVERTISEMENT
ADVERTISEMENT

o Method In-lining
o Local Optimizations
o Control Flow Optimizations
o Constant Folding
o Dead Code Elimination
o Global Optimizations
o Heuristics for optimizing call sites

Advantages of JIT Compiler

o It requires less memory usages.


o The code optimization is done at run time.
o It uses different levels of optimization.
o It reduces the page faults.

Disadvantages of JIT Compiler

o It increases the complexity of the program.


o The program with less line of code does not take the benefit of the JIT
compilation.
o It uses lots of cache memory.

Working of JIT Compiler


If the JIT compiler environment variable is properly set, the JVM reads the .class file (bytecode)
for interpretation after that it passes to the JIT compiler for further process. After getting the
bytecode, the JIT compiler transforms it into the native code (machine-readable code).

o Java Development Kit (JDK) provides the Java compiler (javac) to compile the Java
source code into the bytecode (.class file). After that, JVM loads the .class file at
runtime and transform the bytecode into the binary code (machine code).
Further, the machine code is used by the interpreter.
o We know that the interpretation of Java bytecode reduces the performance of
the native application. It is the reason to implement the JIT compiler. The JIT
compiler accelerates the performance of the application by compiling the
bytecode into native machine code.
o It is enabled by default when a method is invoked. The JVM directly invokes the
compiled code of the method without interpreting it. It does not require much
memory usage.

Therefore, the JIT compiler boosts the performance of the native application. We can understand
the working of the JIT compiler with the help of the following flow chart.
The following figure shows the functional relationship of the JIT compiler with JRE and JVM.

Optimization Levels
It is also known as the optimization level. Each level provides a certain level of performance.
JIT compiler provides the following level of optimization:

o Cold: It used during the startup of the large Java application. The goal is to
achieve the best-compiled code speed.
o Warm: After the starting of the Java application, most of the methods compiled
when they reach the invocation threshold.
o Hot: The methods that consume more than 1% are scheduled for hot
compilation.
o Very Hot: The method scheduled for a very hot if they are not scorching but hot.
o Scorching: The methods that consume more than 5% are scheduled for
scorching compilation.

The default and initial optimization levels are warm. We get better performance if the
optimization level is hotter but it increases the cost in terms of memory and CPU.

At the higher optimization level, the virtual machine uses a thread called sampling. It identifies
the methods that take a long time to execute. The higher optimization level includes the
following techniques:
o Escape Analysis
o Partial Redundancy Elimination

The above techniques use more memory and CPU to improve the performance of the
Java application. It increases the cost of compilation but compensates for performance.

How to Clear Screen in Java


In Java, when we compile and run Java programs, the console or screen gets messed up
with lots of commands and output. To reduce or clear the messing content of the
console, we need to clear the screen in Java so that we can execute programs in a
proper way. In this section, we will learn how to clear the console or screen in Java.

There are the following ways to clear screen or console in Java:

ADVERTISEMENT
ADVERTISEMENT

o Using ANSI escape Code


o Using Platform Specific Command
o Using Command Line Interpreter

Using ANSI Escape Code


ANSI escape sequence is standard in-band signaling to control the cursor position. In
the following example, we have used the escape code \033[H\033[2J. Let's break the
code and understand it separately.

o \033: It represents the ASCII escape character. Its ANSI value is 27. It stands
for ESC.
o [: It represents the escape sequence. It is also known as CSI (Control Sequence
Indicator). The CSI command starts with ESC[ followed by zero or more
parameters.

On combining the above codes, we get \033[ or ESC[.

o \033[H: It moves the cursor at the top left corner of the screen or console.
o \033[2J: It clears the screen from the cursor to the end of the screen.
Let's combine the above two codes, we get \033[H\033[2J. The combination of code
clears the screen or console.

The CSI commands use the default values if we do not specify any parameter in the
command. We can use the following code to clear the screen in Java:

ClearScreenExample1.java

1. public class ClearScreenExample1


2. {
3. public static void main(String[] args)
4. {
5. System.out.print("\033[H\033[2J");
6. System.out.flush();
7. }
8. }

In the above example, we have used the same code (\033[H\033[2J) that we have
explained above. It clears the console. We have also used the flush() function that resets
the cursor position at the top of the screen.

Using Platform-Specific Command


We can also use the command according to the platform we are using. In this method,
first, we get the property of the system by using the getProperty() method of the
System class. After that, we select the command used in the platform to clear the
console.

System.getProperty() Method
It is the static method of the System class. It is used to get the system property indicated
by the specified key. It parses a parameter key of type String. It specifies the name of
the system property. It returns the property of the system and

Syntax:

1. public static String getProperty(String key)

It throws the following exceptions:


o SecurityException: If there exists a security manager and its
checkPropertyAccess() method does not allow access to the specified system
property.
o NullPointerException: It throws the exception if we do not specify the key null.
o IllegalArgumentException: It throws the exception if the key is empty.

Let's create a Java program that clears the console using the platform-specific
command.

ClearScreenExample2.java

1. public class ClearScreenExample2


2. {
3. public final static void clearConsole()
4. {
5. public static void main(String[] args)
6. {
7. try
8. {
9. final String os = System.getProperty("os.name");
10. if (os.contains("Windows"))
11. {
12. Runtime.getRuntime().exec("cls");
13. }
14. }
15. catch (final Exception e)
16. {
17. e.printStackTrace();
18. }
19. }

In the above example, we have specified the Windows operating system and the
command that is used to clear the console is cls. We can also use the following code in
the above program:

1. public final static void clearConsole()


2. {
3. try
4. {
5. final String os = System.getProperty("os.name");
6. if (os.contains("Windows"))
7. {
8. Runtime.getRuntime().exec("cls");
9. }
10. else
11. {
12. Runtime.getRuntime().exec("clear");
13. }
14. }
15. catch (final Exception e)
16. {
17. e.printStackTrace();
18. }
19. }

Using Command Line Interpreter


In this method, we invoke the command line interpreter (CMD). After invoking the
interpreter executes the cls command. It allows executing the built-in commands. Now
we need to connect the interpreter output channel with the Java process output
channel. It can be done by using the inheritIO() method.

ClearScreenExample3.java

1. import java.io.IOException;
2. public class ClearScreenExample3
3. {
4. public static void main(String... arg) throws IOException, InterruptedException
5. {
6. new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
7. }
8. }

Once the above program connects with the console, it starts from a command line
without output redirection and clears the screen or console.

What is Java IDE?


Java IDE (Integrated Development Environment) is a software application that enables
users to write and debug Java programs more easily. Most IDEs have features such as
syntax highlighting and code completion that helps users to code more easily. Usually,
Java IDEs include a code editor, a compiler, a debugger, and an interpreter that the
developer may access via a single graphical user interface. Java IDEs also provide
language-specific elements such as Maven, Ant building tools, Junit, and TestNG for
testing.

The Java IDE or Integrated Development Environment provides considerable support for
the application development process. Through using them, we can save time and effort
and set up a standard development process for the team or company. Eclipse,
NetBeans, IntelliJ IDEA, and many other IDE's are most popular in the Java IDE's that
can be used according to our requirements. In this topic, we will discuss the best Java
IDE's that are used by the users.

Best Java IDEs


The following are the best Java IDEs that are mostly used in the world:

ADVERTISEMENT
ADVERTISEMENT

o Eclipse
o NetBeans
o IntelliJ IDEA
o BlueJ
o JCreator
o JDeveloper
o MyEclipse
o Greenfoot
o DrJava
o Xcode
o Codenvy

Eclipse
It is a Java-based open-source platform that enables us to create highly customized IDEs
from Eclipse member's plug-in components. This platform is also suitable for beginners
to create user-friendly and more sophisticated applications. It contains many plugins
that enable developers to develop and test code written in different languages. Some of
Eclipse's features are as follows:

1. Eclipse provides powerful tools for different software development processes,


such as charting, reporting, checking, etc. so that Java developers can build the
application as quickly as possible.
2. Eclipse can be used on platforms such as MacOS, Linux, Windows, and Solaris.
3. Eclipse could also make several mathematical documents with LaTeX using both
the TeXlipse plug-in and Mathematica software packages.
NetBeans
NetBeans is a Java-based IDE and basic application platform framework. Besides
Java, JavaScript and JavaFX, NetBeans supports PHP, C/C++, Groovy,
and HTML5 languages. It is a free and open-source Java IDE that enables Java
developers to develop various applications using different module sets. Some of the
following features of NetBeans are as follows:

1. NetBeans is available for various operating systems, such as Linux, MacOS,


Windows, Solaris, etc.
2. Although NetBeans is mainly a Java IDE, it has extensions to operate in many
other programming languages, such as C, PHP, C++, JavaScript, HTML5, etc.
3. NetBeans may be used on different systems such as MacOS, Windows, Solaris
and Linux.
IntelliJ IDEA
It is a free and open-source commercial Java IDE. It has two versions that are a paid-up
Ultimate edition and a free and open-source community edition. Some of the features
of the IDEA IntelliJ are as follows:

1. IntelliJ IDEA has several features to make programming easier, like code
completion, debugging, XML editing support, code refactoring, code checks,
TestNG, unit testing, etc.
2. Both versions of IntelliJ IDEA support different programming languages like Java,
Kotlin, Groovy, Scala, etc.
BlueJ
It is a Java IDE that is widely used by the world's Java programmers. However, it was
mainly designed for educational purposes, but also useful for software development.
Some of BlueJ's features are as follows:

1. The BlueJ main screen displays the current development application's class
structure, which is simple to access and change objects.
2. BlueJ's basic design is distinct from other IDE's because it was specifically
designed to teach OOPS to beginners.
JCreator
It is another lightweight Java IDE developed by Xerox Software. It has a similar graphical
interface to Microsoft's Visual Studio. It is available in three different versions: Lite
Edition, Pro Edition and Life-Pro Edition. Unlike Java IDEs, which are developed using
Java, JCreator is developed completely in C++. In addition, it does not require a JRE for
Java code execution. The developer community believes that JCreator is quicker than
most traditional Java IDEs for the unique purpose. On the other hand, it's small and
easy, making it perfect for newbies starting with Java. The following are the features of
JCreator IDE:

1. JCreator's paid version has different features similar to other Java IDEs like code
wizards, debugger Ant support, and project management. However, it does not
have advanced features such as automatic refactoring, support for popular
frameworks, etc.
2. Since JCreator is a Java IDE program in C++, there is no need for a JRE to execute
Java code.
3. Despite some limitations, JCreator is a perfect Java IDE for beginners due to its
compact size and higher pace.
4. JCreator can be used on various platforms like Linux and Windows.

JDeveloper
JDeveloper is a free and open-source Java IDE supported by Oracle Corporation. It can
be used to build applications in different languages other than Java, like PL/SQL,
PHP, XML, HTML, JavaScript, SQL, etc. The following are the features of JDeveloper IDE:

1. JDeveloper also simplifies the application development process by offering a


wide range of visual application development tools and all the tools required to
build an advanced coding environment.
2. JDeveloper may implement the Oracle Application Development Framework,
which is an end-to-end Java EE-based framework. It means that the production of
the application process becomes much simpler.
3. It offers several features for the entire application's life cycle that is coding,
debugging, designing, deploying, optimizing, etc.
MyEclipse
It is a unique Java IDE built on top of the Eclipse platform that is created and maintained
by Genuitec. Many tools and techniques available in MyEclipse could be used to develop
Java apps and web development. It also offers support for JavaScript, HTML, Angular,
and TypeScript and provides support for database connectors and application server
connectors. It has five editions: the Professional Edition, the Regular Edition, the Blue
Edition, the Spring Edition and the Bling Edition. Some of MyEclipse's features are as
follows:

1. MyEclipse offers support to web programming languages like HTML, JavaScript,


Angular, TypeScript, etc.
2. Various tools are available in MyEclipse, like visual web designers, spring tools
database tools, persistence tools, etc. that may be used to develop Java apps and
web development.
3. MyEclipse IDE provides various features, including Spring Tooling, WebSphere
Connectors, Maven Project Management, Database Connectors, and Swing GUI
Design Support etc.
Greenfoot
It is an IDE that has been developed to provide high school and undergraduate
education. Greenfoot is free and open-source software that is maintained with the help
of Oracle. Some of Greenfoot's characteristics are as follows:

1. Greenfoot has the ability to show various OOPS features like class & entity
relationships, processes, object interactions, parameters, etc.
2. Two-dimensional graphical applications could be easily built using Greenfoot;
prime examples are simulations, immersive games, etc.
3. Also, as it was intended to be a learning medium, it has easy access to animation
and sound.
DrJava
It is a lightweight Java IDE organization maintained and operated by the JavaPLT
Community at Rice University. It is mainly developed for beginners and students.
However, it is not as advanced as different Java IDE's. It also has a remarkably culture-
free interface. There are following features of DrJava as follows:

1. Unlike other Java IDEs, DrJava has a consistent presence on various platforms. It's
because it was designed using the Swing toolkit of Sun Microsystems.
2. There are various features available for expert Java Developers in DrJava,
including automatic indentation, commenting autocompletion, syntax coloring,
brace matching, etc.
3. It will interactively test the Java code from the console and display the result in
the same console.
Xcode
It is a Java IDE developed by Apple Inc. for MacOS. It can be accessed free of charge.
This IDE comes with several software development tools for the development of TVOS,
MacOS, and iOS software and allows Java programming. Some of the main highlights of
Xcode are the built-in debugger, GUI designer, and autocomplete profile. AppleScript,
Objective-C, C, Objective-C++, C++, Ruby, Python, and Swift are provided by Xcode, in
addition to Java. There are the following features of Xcode as follows:

1. Split Window View and Coding Assistant


2. Code Filter and User Interface Prototyping
3. Version Editor and Source Control
4. Testing and Configurations
5. Quick Access and Schemes Management
Codenvy
It is a commercial Java IDE built on Eclipse Che. Developers can select the IDE from the
three Java IDE variants, which is the creator, enterprise, and team. It is a workspace for
cloud-based and on-demand developers. In addition to writing Java code using a
browser-based editor, java developer may take advantage of the additional features,
including refactoring, syntax highlighting, and code completion.

By providing an easy way to create, debug, edit, and run different projects, the Codenvy
editor also makes things better for programmers. Codenvy's team version is targeted at
teamwork. In addition to Java, it offers various programming languages for both
interpreted and compiled, including C#, JavaScript, C++, and PHP. The following are the
features of the Codenvy IDE:

1. Act with an adaptable and well-paced IDE on-prem or in the cloud with
2. With extensions and assemblies from Eclipse Che, customize the IDE.
3. Start a project, from any device, in seconds.
4. Act online with CLI push, pull, and clone, or offline.
5. Start the create, run, and deploy parallel processes.
Java Logger
In Java, logging is an important feature that helps developers to trace out the errors.
Java is the programming language that comes with the logging approach. It provides
a Logging API that was introduced in Java 1.4 version. It provides the ability to capture
the log file. In this section, we are going to deep dive into the Java Logger API. Also, we
will cover logging level, components, Logging handlers or appenders, logging
formatters or layouts, Java Logger class,

What is logging in Java?


In Java, Logging is an API that provides the ability to trace out the errors of the
applications. When an application generates the logging call, the Logger records the
event in the LogRecord. After that, it sends to the corresponding handlers or appenders.
Before sending it to the console or file, the appenders format that log record by using
the formatter or layouts.

Need for Logging

o It provides the complete tracing information of the application.


o It records the critical failure if any occur in an application.
Components of Logging
The Java Logging components used by the developers to create logs and passes these
logs to the corresponding destination in the proper format. There are the following
three core components of the Java logging API:

o Loggers
o Logging Handlers or Appender
o Logging Formatters or Layouts

Loggers
The code used by the client sends the log request to the Logger objects. These logger
objects keep track of a log level that is interested in, also rejects the log requests that
are below this level.

In other words, it is responsible for capturing log records. After that, it passes the
records to the corresponding appender.

Generally, the Loggers objects are named entities. The entities separated by the dot
operator. For example, java.net, java.awt, etc.

The namespace is managed by the LogManager and it is represented in hierarchical


order. It must be aligned with the packaging namespace. But it is not mandatory to
follow it exactly. We can also create an anonymous Logger but it will not appear in the
shared namespace.

In the logging namespace, the Logger search for the parent loggers. It is closest to the
extant ancestor in the logging namespace. Remember that there is no parent for the
root logger. It inherits the various attributes from their parent such as:

o Logging Levels: If it is specified to null, it traverses towards the parent and


search for the first non-null level.
o Handlers: a logger will log any message to the handlers of the parent recursively
up to the tree.
o Resource bundle names: If any logger has a null resource bundle name, it
inherits any resource bundle name for its parent recursively up to the tree.
Logging Handlers or Appender
Java Logging API allows us to use multiple handlers in a Java logger and the handlers
process the logs accordingly. There are the five logging handlers in Java:

o StreamHandler: It writes the formatted log message to an OutputStream.


o ConsoleHandler: It writes all the formatted log messages to the console.
o FileHandler: It writes the log message either to a single file or a group of
rotating log files in the XML format.
o SocketHandler: It writes the log message to the remote TCP ports.
o MemoryHandler: It handles the buffer log records resides in the memory.

In the Java Logging API, the FileHandler and ConsoleHandler are the two handlers
provided by default. By extending the Handler class or any subclasses (like
MemoryHandler, StreamHandler, etc.), we can create our own and also customize the
Handler class. the selection of the appenders depends on the logging requirements. If
you are not sure which appenders to use, it may affect the application's performance.

ADVERTISEMENT

Example of Custom Java Logging Handler

1. import java.util.logging.LogRecord;
2. import java.util.logging.StreamHandler;
3. public class MyHandler extends StreamHandler
4. {
5. @Override
6. public void publish(LogRecord record)
7. {
8. //add own logic to publish
9. super.publish(record);
10. }
11. @Override
12. public void flush()
13. {
14. super.flush();
15. }
16. @Override
17. public void close() throws SecurityException
18. {
19. super.close();
20. }
21. }

Logging Formatters or Layouts


The logging formatters or layouts are used to format the log messages and convert data
into log events. Java SE provides the following two standard formatters class:

o SimpleFormatter
o XMLFormatter

SimpleFormatter

It generates a text message that has general information. It writes human-readable


summaries of log messages. The ConsoleHandler uses the class to print the log message
to the console. For example, the following console message shows

1. Oct 28, 2020 11:55:55 PM DemoClass main


2. SEVERE: An exception occurred.

XMLFormatter

The XMLFormatter generates the log message in XML format. It writes the detailed XML
structure information. It is the default formatter for the FileHandler. The log entries look
like the following:

1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>


2. <!DOCTYPE log SYSTEM "logger.dtd">
3. <log>
4. <record>
5. <date>2020-10-29T11:59:55</date>
6. <millis>1595664378</millis>
7. <sequence>0</sequence>
8. <logger>DemoClass</logger>
9. <level>SEVERE</level>
10. <class>DemoClass</class>
11. <method>main</method>
12. <thread>1</thread>
13. <message>An exception occurred.</message>
14. </record>
15. </log>

By extending the Formatter class, we can customize and create our own Formatter
class. We can use the customized class with any handlers.

If you are using Logging frameworks, you can use other layouts such as HTML, JSON,
Syslog, plain text, etc.

Example of Customized Formatter Class

1. import java.util.Date;
2. import java.util.logging.Formatter;
3. import java.util.logging.LogRecord;
4. public class MyFormatter extends Formatter
5. {
6. @Override
7. public String format(LogRecord record)
8. {
9. return record.getThreadID()+"::"+record.getSourceClassName()
+"::"+record.getSourceMethodName()+"::"+new Date(record.getMillis())
+"::"+record.getMessage()+"\n";
10. }
11. }

Java Logging Levels


It shows the rough guide to the importance and urgency of the log message, and also
controls the logging details. Each log level object has an integer value. The higher value
indicates higher priorities. There is a total of nine levels, seven standard logs,
and two special log levels. The first three logging levels FINEST, FINER, and FINE
represent the detailed tracing information that includes what is going on in the
application and what happened in the application.

The following table shows the level and the value corresponding to it.

S. Standard Level Value Used For


No. Log
Levels
1 FINEST 300 Specialized
Developer
Information

2 FINER 400 Detailed


Developer
Information

3 FINE 500 General


Developer
Information

4 CONFIG 700 Configuration


Information

5 INFO 800 General


Information

6 WARNING 900 Potential


Problem

7 SEVERE 1000 Represents


serious failure

8 Special OFF Integer.MAX_VALUE Turns off the


Log logging
Levels
9 ALL Integer.MIN_VALUE Captures
everything

Let's discuss each logging level in detail.

o FINEST: It represents the highly detailed tracing message.


o FINER: It represents the detailed tracing message that includes exceptions
thrown by the application, logging details of the method.
o FINE: It represents the most important message out of these.
o CONFIG: It represents the information related to the configuration of the
application. The information may include how much the disk and memory space.
o INFO: The information of the user used by the administrator or other authorities.
o WARNING: It occurs due to user mistake. If a user inputs the wrong credentials,
the application shows a warning.
o SEVERE: It occurs when some critical or terrible errors shown by the application.
In such cases, the application is not able to continue further. The popular
example of a severe level is out of memory and unavailability of the database.
Setting Up the Logging Level
We can use the following statement to set up the logging level.

1. logger.setLevel(Level.CONFIG);

The above statement sets the logging level to CONFIG and provides the information
related to the configuration of the application. It also generates the log from the
specified level to the greater levels.

ADVERTISEMENT

Suppose, we have specified the log level to FINE, then the generated log will
be CONFIG, INFO, WARNING, and SEVERE.

We can also set it to the configuration file just by changing the Logger's configuration,
as we have shown below:

1. ...
2. <Loggers>
3. <Logger name="DemoLogger" level="info">
4. ...

Logging Events
ADVERTISEMENT
ADVERTISEMENT

To log events in Java, you have to make sure that you assign a level to easily filer out the
events. To assign a level and mention a message we can use the methods given below:

Method 1:

1. logger.log(Level.INFO, "Display message");

In the above statement, we have specified the level INFO and the message to be printed
is, Display message.

Method 2:

1. logger.info("Display message");
Logger in Java logs only events that are at or above the INFO level, to make sure this, we
use the setLevel() method.

Java Log Manager


In Java, the LogManager is a class that belongs to the java.util.logging package. It keeps
track the global logging configuration, creates, and maintains the logger instances. We
can also use it to set its own application-specific configuration. It includes the following
two things:

o The hierarchical namespace of named Logger.


o A group of logging control properties that contains the configuration file.

The LogManager can be retrieved by using the getLogManager() method. It


automatically initialized when we create LogManager. This property allows container
applications (such as EJB containers) to substitute their own subclass of LogManager in
place of the default class.

Create New Logger in Java


We can easily create Logger in Java by using the getLogger() method. It finds a logger
if a logger is already defined and returns the same logger, else creates a new logger for
a named subsystem.

If it creates a new logger, its log level will be configured that depend on the
LogManager configuration, also configures the LogManager, and sends the logging
output to its Handlers. It will be registered in the LogManager global namespace.

Syntax:

1. public static Logger getLogger(String name)

It parses the logger name as a parameter. The logger name must be separated by the
dot (.) operator and should be based on the package name or class name of the
subsystem. For example, java.awt, java.net, etc.

It returns a suitable logger and throws NullPointerException if we do not specify the


logger name.

Example:
1. public class Student
2. {
3. private static final Logger logger = Logger.getLogger(Student.class);
4. public void getStudentDetails()
5. {
6. //statements
7. }
8. }

Java Logger Class


Java provides a class Logger that belongs to java.util.logging package. It contains the
methods related to logging.

o It is used to log messages for a specific application component.


o Each Logger track the parent Logger (nearest existing ancestor) in the logger
namespace.
o Loggers also have an associated level. If the level is null, it inherits the level from
its parent Logger.
o It also has a ResourceBundle name associated with it. It is used for localizing
logging messages. Like the logging level, if it does not have its own
ResourceBundle name then it inherits the ResourceBundle name from its parent.
o The logging messages forward to the Handler object that is registered. Further,
the Handler forwards the message to a variety of destinations such as files, OS,
logs, and console, etc.
o All the methods of the Logger are multi-thread safe.

The logger class provides methods for logging that are grouped into the following five
categories:

o It provides a group of log The method takes a log level, a message, and some
optional parameters for the message.
o There is another set of methods called the logp It is the same as the log method
but also takes the class name and method name, explicitly.
o It provides another group of methods called logrb (log that includes resource
bundle). It is similar to the logp methods but also takes the resource bundle
name, explicitly that localize the log message.
o The class also provides a group of methods that trace the method entries is
known as entering
o It also provides methods for tracing the method entries, such as a method that
throws an exception is grouped into throwing exceptions. Similarly, a method
that returns something is grouped into existing methods.
o Also contains a set of convenience methods that are used in the simplest
methods. It is used if the programmer simply wants to log a string at the
specified level. These methods take a message string as an argument.

Therefore, we can conclude that the LogManager performs the actual logging. The
instances of the LogManager accessed by the getLogger() method. The global logger
instance is retrieved by the static field GLOBAL_LOGGER_NAME of the Logger class. It
provides casual use of the Logging package.

Logging Frameworks
We can also use the logging framework to make the logging concept easy. There is the
following popular logging framework used for logging:

o Log4j: Apache Log4j is an open-source Java-based logging utility.


o SLF4J: It stands for Simple Logging Facade for Java (SLF4J). It is an abstraction
layer for multiple logging frameworks such as Log4j, Logback, and
java.util.logging.
o Logback: It is an open-source project designed as a successor to Log4j version 1
before Log4j version 2 was released.
o tinylog(tinylog): It is a light weighted and open-source logger.
Reverse a String Using Recursion in
Java
Recursion in Java is a process in which a method calls itself continuously. In the
programming language, if a program allows us to call a function inside the same
function name, it is known as a recursive call of the function. It makes the code compact
but it is difficult to understand. It is used to solve the complex problem that can be
broken into smaller repetitive problems. Using recursion, we can solve many complex
problems like the factorial program, Fibonacci series, etc. Similarly, we can also
use recursion to reverse a String in Java. In this section, we will learn how to reverse
a string using recursion in Java.

The recursive function performs the following steps to reverse a string:

ADVERTISEMENT
ADVERTISEMENT

o First, remove the first character from the string and append that character at the
end of the string.
o Repeat the above step until the input string becomes empty.

Suppose, the input string JAVATPOINT is to be reversed. We will remove the first
character from the string and append it to a variable reversesting. Let's implement the
functionality in a Java program and reverse the string using recursion.

In the following example, we have created a method named reverseString(). It parses


the string that we want to reverse. Inside the method, first, we have checked that the
string is empty or not. If the string is empty, it returns the same string and also
prints String is empty. We have used the following two methods of the String class:

substring(): It returns the new string that is a substring of the specified string. It parses
a parameter that specifies the starting index (beginning) of the substring.
charAt(): It returns a character at the specified index. The index lies between 0 too
length()-1.

ReverseStringExample1.java

1. public class ReverseStringExample1


2. {
3. //recursive function to reverse a string
4. public String reverseString(String str)
5. {
6. //checks if the string is empty
7. if(str.isEmpty())
8. {
9. System.out.println("String is empty.")
10. //if the above condition is true returns the same string
11. return str;
12. }
13. else
14. {
15. return reverseString(str.substring(1))+str.charAt(0);
16. }
17. }
18. public static void main(String[] args)
19. {
20. ReverseStringExample1 rs = new ReverseStringExample1();
21. String resultantSting1 = rs.reverseString("JAVATPOINT");
22. String resultantSting2 = rs.reverseString("COMPUTER");
23. String resultantSting3 = rs.reverseString("INDIA");
24. System.out.println(resultantSting1);
25. System.out.println(resultantSting2);
26. System.out.println(resultantSting3);
27. }
28. }

Output:
Let's see another example to reverse a string using recursion.

In the following example, we have created a method named reverseString(). It parses


the string that we want to reverse. Inside the method, we have tested two conditions
using the logical OR operator. First, we have compared the string with null and in the
second condition, we have found the length of the string and compared it with 1. If
either or both the conditions return true, the method prints the same string.

In the else part, we have called the reverseString() method recursively that reverse the
string. The method parses a substring returned by the substring() method. The
substring() method also parses the two parameters the begin index and the end index.
It returns the substring of the specified string. Therefore, it reverses the string
recursively.

ReverseStringExample2.java

1. class ReverseStringExample2
2. {
3. //recursive function to reverse a string
4. void reverseString(String string)
5. {
6. if ((string==null)||(string.length() <= 1))
7. System.out.println(string);
8. else
9. {
10. System.out.print(string.charAt(string.length()-1));
11. reverseString(string.substring(0,string.length()-1));
12. }
13. }
14. public static void main(String[] args)
15. {
16. //string to be reversed
17. String str = "The purpose of our lives is to be happy.";
18. ReverseStringExample2 rs = new ReverseStringExample2();
19. //invoking the recursive function and passing the string to be reversed
20. rs.reverseString(str);
21. }
22. }

Output:

Float Vs Double Java


In Java, data types specify the size and type of values. It is used to store the floating
values of an identifier. Data types are classified into two categories, primitive and non-
primitive. Primitive data type includes all the predefined data types such as Integer,
Character, Boolean, Floating-Point, etc. while the non-primitive data-type includes
user-defined data types such as Classes, Arrays, and Interfaces, etc.
Both float and double data types store floating values but still, they are different. In this
section, we will learn the differences between float and double datatype in Java.

There are two types of Floating-Point data types:

ADVERTISEMENT
ADVERTISEMENT

o float Data Type


o double Data Type

Both, float and double represents the floating-point numbers that store the decimal
values.

Floati Valu Size Storage Defa Precis Deci Rang Accur


ng- es (bits Require ult ion mal e acy
Point )* ment Valu Digits
Data (bytes) e
Type

float IEEE 32 4 0.0f Single 6 3.4e- Low


754 decima 038 to
Floatin l digits 3.4e+0
g- 38
Point

double IEEE 64 8 0.0d Double 15 1.7e- High


754 decima 308 to
Floatin l digits 1.7e+3
g- 08
Point

*The size bits include the following:

Bits float double

Sign 1 1

Exponent 8 11

Mantissa 23 52

Single-Precision: It consists of one sign bit (S), eight exponent bits (E), and twenty-
three mantissa bits (M).

Double-Precision: It consists of one sign bit (S), eleven exponent bits (E), and fifty-
two mantissa bits (M).
float Data Type
It is a 32-bit, single-precision IEEE 754 (Standard for Floating-Point Arithmetic) floating-
point number. It means that it gives 6-7 decimal digits precision. It is used if we want to
use memory effectively because it takes less memory in comparison to double data
type. To define a float value, we must use a suffix f or F. Its default value is 0.0f. By
default, float numbers are treated as double in Java.

For example, if we define a float number as:

1. float height = 167.7

The above declaration of float variable gives the compilation error. We can correct the
error by adding a suffix f or F.

1. float height = 167.7f


2. or
3. float height = 167.7F

double Data Type


The double data type is a 64-bit double-precision IEEE 754 floating-point number. It
means that it gives 15-16 decimal digits precision. It consumes more memory in
comparison to the float data type. It is used to store decimal values. Its default value is
0.0d. It is optional to add suffix d or D. For example:

1. double price = 987.90D


2. or
3. double price = 987.90d
4. or
5. double price = 987.90

float Vs double Data Type


The double data type is more accurate than the float data type. The following table
summarizes the differences between float and double data types.

Basis float Data Type double Data Type

Memory It occupies 4 bytes. It occupies 8 bytes.

Accuracy Its accuracy is low. Its accuracy is high.

Precision It follows single-precision (6-7 It follows double-precision (15-16


decimal digits). decimal digits).

Keyword used The float keyword is used to The double keyword is used to
define a float number. define a double-precision number.

Wrapper Class Its wrapper class Its wrapper class


is java.lang.Float. is java.lang.Double.

Default Data Java does not use it as the It is the default data type for
Type default floating-point number. floating-point numbers.

Data Loss There will be no data loss if we There will be data loss if we
convert float to double. convert double to float.

Uses It should be used where less It is used where more accuracy is


accuracy is required and required and also requires more
storage is a constraint. precision.
Suffix It uses F or f as a suffix. It is It uses d or D as a suffix. It is
mandatory to add a suffix if you optional to add a suffix if you are
are declaring a float variable. declaring a double variable.

Representatio 28.96f or 28.96F 12.5 or 12.5D or 12.5d


n

Similarities Between float and double Data


Type
o Real numbers can be represented by both data types.
o Both float and double data types are not precise, hence, they are approximate
value.

Which floating-point data type in Java we


should use?
double is more precise than float. So, if a more precise and accurate result is required
use double. Another reason to use double is that if the number is not fitting in the range
offered by the float then use double. We should use float if we have memory constraint
because it occupies half-space than double.

We recommend you to use double over float if there is no memory and space constraint
and when more precision is needed. It is advisable to go with the float, if memory is a
concern, and the result in 16 precision decimal digits are not required.

The following two Java programs clearly show the differences between float and double
data type.

FloatDataTypeExample.java

1. public class FloatDataTypeExample


2. {
3. public static void main(String args[])
4. {
5. float x = 1.0f, y = 3.0f; //defining x and y as float
6. float z = x / y; //divides x by y and stores the result in the variable z
7. System.out.println("x/y = " + z); //prints the result
8. }
9. }

Output:

x/y = 0.33333334

DoubleDataTypeExample.java

1. public class DoubleDataTypeExample


2. {
3. public static void main(String args[])
4. {
5. double x = 1.0, y = 3.0; //defining x and y as double
6. double z = x / y; //divides x by y and stores the result in the variable z
7. System.out.println("x/y = " + z); //prints the result
8. }
9. }

Output:

x/y = 0.3333333333333333

Through the above two examples, it is clear that the double data type takes more
memory to store a double-precision number and also gives the more accurate result up
to 16 decimal digits. While the float data type takes less space to store single-precision
numbers and it gives results up to 6 decimal places.
Stack Vs Heap Java
In Java, memory management is a vital process. It is managed by Java automatically. The
JVM divides the memory into two parts: stack memory and heap memory. From the
perspective of Java, both are important memory areas but both are used for different
purposes. The major difference between Stack memory and heap memory is that
the stack is used to store the order of method execution and local variables while the
heap memory stores the objects and it uses dynamic memory allocation and
deallocation. In this section, we will discuss the differences between stack and heap in
detail.

Stack Memory
The stack memory is a physical space (in RAM) allocated to each thread at run time. It is
created when a thread creates. Memory management in the stack follows LIFO (Last-In-
First-Out) order because it is accessible globally. It stores the variables, references to
objects, and partial results. Memory allocated to stack lives until the function returns. If
there is no space for creating the new objects, it throws
the java.lang.StackOverFlowError. The scope of the elements is limited to their threads.
The JVM creates a separate stack for each thread.

Heap Memory
It is created when the JVM starts up and used by the application as long as the
application runs. It stores objects and JRE classes. Whenever we create objects it
occupies space in the heap memory while the reference of that object creates in the
stack. It does not follow any order like the stack. It dynamically handles the memory
blocks. It means, we need not to handle the memory manually. For managing the
memory automatically, Java provides the garbage collector that deletes the objects
which are no longer being used. Memory allocated to heap lives until any one event,
either program terminated or memory free does not occur. The elements are globally
accessible in the application. It is a common memory space shared with all the threads.
If the heap space is full, it throws the java.lang.OutOfMemoryError. The heap memory is
further divided into the following memory areas:

ADVERTISEMENT
ADVERTISEMENT

o Young generation
o Survivor space
o Old generation
o Permanent generation
o Code Cache

The following image shows the allocation of stack memory and heap space.
Difference Between Stack and Heap Memory
The following table summarizes all the major differences between stack memory and
heap space.

Parameter Stack Memory Heap Space

Application It stores items that have a very It stores objects and Java
short life such as methods, Runtime Environment (JRE)
variables, and reference classes.
variables of the objects.

Ordering It follows the LIFO order. It does not follow any order
because it is a dynamic memory
allocation and does not have any
fixed pattern for allocation and
deallocation of memory blocks.

Flexibility It is not flexible because we It is flexible because we can alter


cannot alter the allocated the allocated memory.
memory.

Efficiency It has faster access, allocation, It has slower access, allocation,


and deallocation. and deallocation.

Memory Size It is smaller in size. It is larger in size.

Java Options We can increase the stack size by We can increase or decrease the
Used using the JVM option -Xss. heap memory size by using the -
Xmx and -Xms JVM options.

Visibility or The variables are visible only to It is visible to all threads.


Scope the owner thread.

Generation of When a thread is created, the To create the heap space for the
Space operating system automatically application, the language first
allocates the stack. calls the operating system at run
time.

Distribution Separate stack is created for each It is shared among all the
object. threads.

Exception JVM throws JVM throws


Throws the java.lang.StackOverFlowErr the java.lang.OutOfMemoryErr
or if the stack size is greater than or if the JVM is unable to create a
the limit. To avoid this error, new native method.
increase the stack size.

Allocation/ It is done automatically by It is done manually by


Deallocation the compiler. the programmer.

Cost Its cost is less. Its cost is more in comparison to


stack.

Implementati Its implementation is hard. Its implementation is easy.


on

Order of Memory allocation is continuous. Memory allocated


allocation in random order.

Thread-Safety It is thread-safe because each It is not thread-safe, so properly


thread has its own stack. synchronization of code is
required.

Abstraction Vs Encapsulation
Java is an object-oriented programming language and it follows OOPs concepts. The
OOPs concepts include classes, objects, polymorphism, inheritance. There are two other
features of OOPs i.e. abstraction and encapsulation. They both seem very similar but
totally different in concept and implementation. The major difference between
abstraction and encapsulation is that abstraction hides the code complexity while
encapsulation hides the internal working from the outside world. In this section, we will
discuss abstraction and encapsulation and the differences between abstraction and
encapsulation in Java.

Abstraction
It is a feature of OOPs. It is used to hide the unnecessary information or data from the
user but shows the essential data that is useful for the user. It can be achieved by using
the interface and the abstract class. In interfaces, only the methods are exposed to the
end-user. The best example of abstraction is a TV remote. The user only interacts with
the outer interface that is nothing but keys. The user only knows which key to press for
what function.

Let's understand the abstraction through a Java program.

1. //abstract class
2. abstract class Shape
3. {
4. //abstract method
5. //note that we have not implemented the functionality of the method
6. public abstract void draw();
7. }
8. class Circle extends Shape
9. {
10. //implementing functionality of the abstract method
11. public void draw()
12. {
13. System.out.println("Circle!");
14. }
15. }
16. //main class
17. public class Test
18. {
19. public static void main(String[] args)
20. {
21. Shape circle = new Circle();
22. //invoking abstract method draw()
23. circle.draw();
24. }
25. }

Encapsulation
It is also a feature of OOP. It is used to bind up the data into a single unit called class. It
provides the mechanism which is known as data hiding. It is an important feature of
OOPs. It prevents to access data members from the outside of the class. It is also
necessary from the security point of view.

Let's understand the abstraction through a Java program.

EncapsulationDemo.java

1. //A Java class to test the encapsulated class Account


2. public class EncapsulationDemo
3. {
4. public static void main(String[] args)
5. {
6. //creating instance of Account class
7. Account acc=new Account();
8. //setting values through setter methods
9. acc.setAcc_no(7560504000L);
10. acc.setName("Mark Dennis");
11. acc.setEmail("md123@gmail.com");
12. acc.setAmount(500000f);
13. //getting values through getter methods
14. System.out.println(acc.getAcc_no()+" "+acc.getName()+" "+acc.getEmail()+"
"+acc.getAmount());
15. }
16. }

Account.java

1. class Customer
2. {
3. //private data members
4. private long cstmr_id;
5. private String cstmr_name, cstmr_email;
6. private float amount;
7. //public getter and setter methods
8. public long getAcc_no()
9. {
10. return acc_no;
11. }
12. public void setAcc_no(long acc_no)
13. {
14. this.acc_no = acc_no;
15. }
16. public String getName()
17. {
18. return name;
19. }
20. public void setName(String name)
21. {
22. this.name = name;
23. }
24. public String getEmail()
25. {
26. return email;
27. }
28. public void setEmail(String email)
29. {
30. this.email = email;
31. }
32. public float getAmount()
33. {
34. return amount;
35. }
36. public void setAmount(float amount)
37. {
38. this.amount = amount;
39. }
40. }
Difference Between Abstraction and
Encapsulation

Abstraction Encapsulation

Abstraction is a feature of OOPs Encapsulation is also a feature of OOPs. It hides


that hides the unnecessary detail the code and data into a single entity or unit so
but shows the essential that the data can be protected from the outside
information. world.

It solves an issue at Encapsulation solves an issue


the design level. at implementation level.

It focuses on the external lookout. It focuses on internal working.

It can be implemented It can be implemented by using the access


using abstract modifiers (private, public, protected).
classes and interfaces.

It is the process It is the process of containing the information.


of gaining information.

In abstraction, we use abstract We use the getters and setters methods to hide
classes and interfaces to hide the the data.
code complexities.

The objects are encapsulated that The object need not to abstract that result in
helps to perform abstraction. encapsulation.

HashSet vs TreeSet
In Java, the entire Collections Framework is built upon a set of standard interfaces.
Several standard implementations (such as LinkedList, HashSet, and TreeSet) of these
interfaces are provided that we may use as-is. In this section, first, we will
discuss HashSet and TreeSet with proper examples. Also, we will discuss
the differences and similarities between HashSet and TreeSet.
The following figure shows the hierarchy of HashSet and TreeSet in the Collections
framework.

HashSet
HashSet is a generic class of the Java collection framework. It extends AbstractSet and
implements the Set interface. It creates a collection that uses a hash table for storage.
The hash table stores the information by using the hashing mechanism.

Hashing uses the informational content to determine a unique value which is known
as hash code. It is used as the index in which data is stored that is associated with the
key. The transformation of the key into hash code performed automatically. The benefit
of hashing is that it allows the execution time of add, contain, remove, and size
operation to remain constant even for large sets. Its time complexity for the operation
search, insert, and delete is O(1).

The HashSet class does not provide any additional methods. It uses the methods of its
superclasses and interfaces. It is to be noted that it does not guarantee the order of its
elements.

Let's understand the HashSet through a Java program.

HashSetExample.java

1. import java.util.HashSet;
2. public class HashSetExample
3. {
4. public static void main(String[] args)
5. {
6. //creating a HashSet
7. HashSet<String> hs = new HashSet<String>();
8. // add elements to HashSet
9. hs.add("New York City");
10. hs.add("Houston");
11. hs.add("Tucson");
12. hs.add("Los Angeles");
13. hs.add("Chicago");
14. hs.add("Boston");
15. hs.add("Denver");
16. //adding a duplicate element to the HashSet
17. hs.add("Chicago");
18. //prints the HashSet element on the console
19. System.out.println("HashSet elements are: ");
20. for (String temp : hs)
21. {
22. System.out.println(temp);
23. }
24. }
25. }

Output

In the above output, we observe two things. The first one is the elements are not sorted
in the natural order and the second thing is that the duplicate element Chicago has
been removed.

TreeSet
TreeSet is a class of Java collection framework that extends AbstractSet and implements
the Set, NavigableSet, and SortedSet interface. It creates a collection that uses a tree for
storage.

TreeSet is a generic class of the Java collection framework. It implements the Set
interface. It uses TreeMap internally to store the TreeSet elements. By default, it sorts
the elements in natural order (ascending order). The order of sorting depends on the
Comparator that we have parsed. If no Comparator is parsed, it sorts the elements in the
natural order.

Its performance is slow in comparison to HashSet because TreeSet sorts the elements
after each insertion and deletion operation.

It uses two methods comaperTo() or compare() to compare the elements. It is to be


noted that the implementation of TreeSet is not synchronized. It means that it is not
thread-safe. The implementation must be synchronized externally if multiple threads
accessing a TreeSet concurrently and a thread try to modify the TreeSet.

It does not allow to store null elements. It throws NullPointerException if we try to


insert a null element. It requires more memory than TreeSet because it also maintains
the comparator to sort the elements.

Its time complexity for the operation search, insert, and delete is O(log n) which is much
higher than HashSet. It uses a self-balancing BST (Red-Black Tree) to implement the
TreeSet.

Let's understand the TreeSet through a Java program.

TreeSetExample.java

1. import java.util.TreeSet;
2. public class TreeSetExample
3. {
4. public static void main(String[] args)
5. {
6. //creating a TreeSet
7. TreeSet<String> ts= new TreeSet<String>();
8. //adding elements to TreeSet
9. ts.add("Dell");
10. ts.add("HP");
11. ts.add("Apple");
12. ts.add("Acer");
13. ts.add("Asus");
14. ts.add("Lenovo");
15. ts.add("Samsung");
16. //try to a duplicate element
17. ts.add("Asus");
18. //prints the TreeSet elements on the console
19. System.out.println("TreeSet elements are: ");
20. for (String temp : ts)
21. {
22. System.out.println(temp);
23. }
24. }
25. }

Output

In the above output, we observe two things. The first one is the elements are sorted in
the natural order and the second thing is that the duplicate elements Asus has been
deleted.

We have deeply understood the HashSet and TreeSet. Now, we will move to the
differences between the two.

Difference Between HashSet and TreeSet

Parameters HashSet TreeSet

Ordering or It does not provide a guarantee It provides a guarantee to sort the


Sorting to sort the data. data. The sorting depends on the
supplied Comparator.

Null Objects In HashSet, only an It does not allow null elements.


element can be null.

Comparison It It
uses hashCode() or equals() m uses compare() or compareTo() m
ethod for comparison. ethod for comparison.

Performance It is faster than TreeSet. It is slower in comparison to


HashSet.

Implementati Internally it uses HashMap to Internally it uses TreeMap to store


on store its elements. its elements.

Data HashSet is backed up by a hash TreeSet is backed up by a Red-


Structure table. black Tree.

Values Stored It allows It allows only homogeneous value.


only heterogeneous value.

There are some similarities between HashSet and TreeSet:

ADVERTISEMENT
ADVERTISEMENT

o Both the classes implement the Set interface.


o They do not allow duplicate values.
o Both HashSet and TreeSet are not thread-safe.
o They are not synchronized but if we want to make them synchronize, we can use
Collections.synchronizedSet() method.
o The iterator used in both classes are fail-fast in nature. They
throw ConcurrentModificationException if we try to modify an iterator once it
is created.
o Both uses the shallow copy technique to create the clone of their objects by
using the clone() method.

Which one is better to use?


Use HashSet if you want elements in sorted order else use HashSet because its
performance is fast in comparison to TreeSet.
Public Vs Private Java
In Java, public and private are keywords that are known as an access modifier or specifier.
It restricts the scope or accessibility of a class, constructor, variables, methods, and data
members. It depends on which it is applied. Java provides the four types of access
modifiers: public, private, protected, and default. But in this section, we will discuss only
two public and private, and also discuss the difference between public and private access
specifier with example.

Access modifiers control whether other classes can use a particular field or invoke a particular
method. Java provides two levels of access control:

ADVERTISEMENT
ADVERTISEMENT

o Top-Level: At this level, we can use only a public


o Member Level: At this level, we can use public, private,
protected and package-private (if we use no explicit modifier is known as
package-private).
The following table shows the access level to members permitted by the public and private
modifiers.

Still not clear the differences between the two? Let me show you a figure that demonstrates how
access levels affect visibility. The following figure shows the two packages p1 and p2. Each
package contains two classes Demo1 and Demo2 (in package p1),
and Demo3 and Demo4 (in package p2).

The following table describes the visibility of the classes if we make the classes public and
private one by one. In the above figure the Demo1 is the only class that is visible for each access
modifiers.
Let's discuss it in detail.

Public Access Modifier


It can be specified by using the public keyword. Its scope or accessibility is the widest among
other access specifiers. The variables, classes, and methods declared as public can be accessed
from everywhere in the program. It does not impose restrictions on the scope of public data
members. If we declare methods and classes as public, they also violate the principle
of encapsulation. We can also use it with the top-level classes.

Let's use the private access specifier in a Java program for better understanding.

Demo1.java

1. package p1;
2. public class Demo1
3. {
4. public void show()
5. {
6. System.out.println("Javatpoint");
7. }
8. }

Demo2.java

1. package p2;
2. import p1.*;
3. class Demo2
4. {
5. public static void main(String args[])
6. {
7. Demo1 obj = new Demo1();
8. obj.show();
9. }
10. }

Output

Javatpoint
Private Access Modifier
It is the opposite of the public modifier. It can be specified by using the private keyword
followed by class name (applied only on nested classes) or method name or data member. We
cannot use the private access specifier with the top-level classes or interfaces. The variables,
methods, and classes declared as private can be accessed only in the class in which they are
declared or by inheriting the parent classes. It is the most restricted access specifier in Java. It is
the heights form of encapsulation.

o We cannot override the methods that are declared as private.


o If we use the private modifier with the constructor, we avoid it from being sub-
classed.
o It hides the classes from the other classes within the same package.

Let's use the private access specifier in a Java program for better understanding.

In the following example, we have declared two classes: Demo1 and Demo2. In the class
Demo1, we have defined a method show() as private. The class Demo2 contains the main()
method in which we have created an object of the class Demo1. After that, we are trying to
access the private method of the class Demo1 from the class Demo2, that is not possible. But
still, we will execute the program to see which error it shows.

1. class Demo1
2. {
3. //defining method as private
4. private void show()
5. {
6. System.out.println("Javatpoint");
7. }
8. }
9. public class Demo2
10. {
11. public static void main(String args[])
12. {
13. Demo1 obj = new Demo1();
14. //trying to access private method of the class Demo1
15. obj.show();
16. }
17. }

When we execute the above program, it shows the following error:

Difference Between Public and Private


Access Specifier in Java
The major difference between public and private modifiers is its visibility. Java categories the
visibility for class members as follows:

o Subclasses in the same package


o Non-subclasses in the same package
o Subclasses in different packages
o Classes neither in the same package nor subclasses

Which one we should use?


We should use public access modifier if we want to make the method or property visible from
anywhere, other classes, and instances of the object. Use the private access modifier if you want
to make the method or property visible in its own class only. Avoid public fields except for
constants.

ADVERTISEMENT

What is Java Used For?


Java is the most popular, widely used object-oriented programming language. The security
feature of Java makes it popular and widely used. It used by many Java enthusiasts for different
purposes. By using Java, we can develop a variety of applications such as enterprise
applications, network applications, desktop applications, web applications, games, android app,
and many more. In this section, we will focus on what is Java used for, the applications of
Java, and why we use Java.
Applications of Java Programming Language
The expansion of the Java programming language is very wide and it is proved by the
statement 3 Billion Devices Runs Java which is shown during the installation of
Java. Java provides a rich and wide range of API that helps programmers to develop
applications. Using Java, we can develop different applications for different purposes. We can
use Java technology to develop the following applications:

ADVERTISEMENT
ADVERTISEMENT

o Mobile App Development


o Desktop GUI Applications
o Web-based Applications
o Gaming Applications
o Big Data Technologies
o Distributed Applications
o Cloud-based Applications
o IoT Applications

Mobile App Development


The Java programming language can be considered as the official language for mobile
application development. Most of the android applications build using Java. The most
popular android app development IDE Android Studio also uses Java for developing android
applications. So, if you are already familiar with Java, it will become much easier to develop
android applications. The most popular android applications Spotify and Twitter are developed
using Java.

Desktop GUI Applications


We can also develop a GUI application using Java. Java provides AWT, JavaFX, and Swing for
developing the GUI based desktop application. The tools contain the pre-assembled components
like list, menu, button.

Web-based Applications
It is also used for developing the web-based application because it provides vast support for web
development through Servlet, JSP, and Struts. It is the reason that Java is also known as a server-
side programming language. Using these technologies, we can develop a variety of applications.
The most popular frameworks Spring, Hibernate, Spring Boot, used for developing web-based
applications. LinkedIn, AliExpress, web.archive.org, IRCTC, etc. are the popular websites
that are written using Java programming language.

Game Development
Java is widely used by game development companies because it has the support of the open-
source most powerful 3D engine. The engine provides unparalleled capacity when it comes to
the context of the designing of 3D games. The most popular games developed in Java
are Minecraft, Mission Impossible III, etc. There are some popular Frameworks and Libraries
available for Game Development, like - LibGDX and OpenGL.

Big Data Technology


As many programming languages are available for Big Data Technology but still Java is the first
choice for the same. The tool Hadoop HDFS platform for processing and storing big data
applications is written in Java. In big data, Java is widely used in ETL applications such as
Apache Camel and Apache Kafka. It is used to extract and transform data, and load in big data
environments.

Distributed Applications
The JINI (Java Intelligent Networking Infrastructure) provides the infrastructure to register and
find distributed services based on its specification. It implements a mechanism that is known as
JavaSpaces. It supports the distribution, persistence, and migration of objects in a network.

Cloud-Based Applications
A cloud application is the on-demand availability of IT resources via the internet. The cloud-
based application provides the service at a low cost. Java provides the environment to develop
cloud-based applications. We can use Java to develop SaaS (Software as a Service), LaaS
(Logging as a Service), and PaaS (Platform as a Service). The cloud application widely used to
share data between companies or to develop applications remotely.

IoT Application
IoT is a technology that connects the devices in its network and communicates with them. IoT
has found almost in all the small devices such as health gears, smartphones, wearables, smart
lighting, TVs, etc. For developing the IoT application there is a lot of programming languages
that can be used but Java offers an edge to developers that is unparalleled. IoT programmers
gravitate towards Java because of its security, flexibility, and versatility.

Why we use Java?


In comparison to other programming languages, Java stands alone for its security and
functionality. Java isolates itself from other programming languages because of functionality and
security and it is relevant too. There are some other reasons to use Java are as follows:

o Scalability: Scalability adds capacity to our system. It improves the capacity of


the system by adding the system resources without affecting the deployment
architecture. We can achieve scalability by increasing the resources such as RAM
and CPU in a single system. It is important because it handles the workload,
increases the system performance, and maximizes productivity.
o Cross-Platform: Cross-platform means, a compiled Java program can be run on
all the platforms. Remember that the system must have JVM. After compiling a
Java program, the Java code gets converted into the bytecode which is platform-
independent. This bytecode is understood by the JVM. We can run this bytecode
on any platform.
o Memory-Management: Java provides its own mechanism for managing the
memory is known as garbage collection. We need not to care about memory and
do not required to implement it to manage the memory. It automatically deletes
the objects when they no longer used by the application. It improves the speed
of the application.
o Multi-threading: Thread is a light-weight subprocess. Multi-threading in Java
allows concurrent execution of two or more threads simultaneously. It maximizes
the utilization of the CPU.

Top Companies that Use Java


There is a majority of companies such as, Uber, Pinterest, Google, Instagram, Spotify,
Netflix, Airbnb, etc. that use Java in their tech stack. We have listed some companies or
organizations and their projects. It will help you to decide which programming language you
have to choose for the next project.

NASA Word Wind


NASA Word Wind is the project of an independent agency of the U.S. federal government
NASA. It is a fully 3D virtual globe that provides geographic information. It uses imagery and
aerial photography received from the NASA satellite and builds 3D models of the planets.

It is an open-source proprietary software written in Java and supports all operating systems. In
this project, the OpenGL API is used to provide 2D and 3D graphics that interact with the
graphics processing unit. It also shows the data in real-time by using the GPS plugin such as
displaying clouds, hurricanes, earthquakes, etc. Using this application, we can search for
locations by geographical names, set visible layers and viewing angles, and much more.

Netflix
Netflix is one of the most popular and largest US entertainment company that provides movies
and TV shows on streaming multimedia. Most of the applications of Netflix is developed using
Java. With a slight mixture of C++, android and android TV applications are almost build in
Java.

Spotify
Spotify is an online audio streaming service that uses Java to implement the functionality of its
web application. For example, log and stabilize, and data transfer. The android application of
Spotify uses Java.

Minecraft
Minecraft is a famous computer game that is written in Java. The Minecraft Java edition
comes with Java 1.8 and Minecraft used it by default.

Static Function in Java


In Java, the static keyword can be used with variable, constant, and functions. The main
purpose of using the static keyword is to manage the memory so that we can use the
memory efficiently. In this section, we will discuss the static function in Java.

Static Function
If the keyword static is prefixed before the function name, the function is called a static
function. It is often called a method.

A method is a group of variables and statements that functions together as a logical


unit. Like fields, methods can have modifiers (like private, public, or static). Methods also
have a return type (may be void if the method returns nothing). The return type can be a
reference type (such as an object or an array). A method can have any number of
parameters or arguments.

When a function is static, it is really part of the class and not part of the individual
objects in the class. It means that static functions exist even before creating any objects.

The best example of a static method is the main() method.

Properties of Static Function


ADVERTISEMENT
ADVERTISEMENT

o It can access only static members.


o It can be called without an instance.
o It is not associated with the object.
o Non-static data members cannot be accessed by the static function.

Declaring a Static Function


The declaration of a static function in Java is the same as the declaration of a method.
The function has two parts function prototype and body of the function.
The function prototype contains the function signature that includes the function
name, return type, access specifier, and the parameters list. The function body contains
the logic or functionality to be performed.

Syntax:

1. [access specifier] static [return type] [function name] (parameter list)


2. {
3. //body of the function
4. }

In the above syntax, the access specifier and the parameter list are optional. A function
may or may not have a parameter list. For example:

1. public static int sum(int a, int b)


2. {
3. int c=a+b;
4. return c;
5. }

Calling Static Function


In Java, we cannot call the static function by using the object. It is invoked by using
the class name.

ADVERTISEMENT

1. [class name].[method name]

For example:

1. Math.sqrt(a); //calling the square root function of the Math class

Example of Static Function in Java


Let's create a Java program from which we can clearly understand the difference
between static and non-static functions.

StatciFunctionExample.java
1. class Demo
2. {
3. //non-static function
4. void display()
5. {
6. System.out.println("A non-static function is called.");
7. }
8. //static function
9. static void show()
10. {
11. System.out.println("The static function is called.");
12. }
13. }
14. public class StaticFunctionExample
15. {
16. public static void main(String args[])
17. {
18. //creating an object of the class A
19. Demo obj = new Demo();
20. //calling a the non-static function by using the object of the class
21. obj.display();
22. //calling a static function by using the class name
23. Demo.show();
24. }
25. }

Output:

A non-static function is called.


The static function is called.

Let's create a Java program and call a static method from another static method even
without creating an object of the class.

CalculateCube.java

1. public class CalculateCube


2. {
3. //defining a static method
4. static void cube()
5. {
6. int x=7*7*7;
7. System.out.println("Cube of 7 is: "+x);
8. }
9. public static void main(String args[])
10. {
11. //calling the static method without using the object of the CalculateCube class
12. cube();
13. }
14. }

Output:

ADVERTISEMENT

Cube of 7 is: 343

Restrictions of the Static Method


There are two main restrictions for the static method. They are:

o The static method cannot use non-static data members or call a non-static
method directly.
o this and super keyword cannot be used with a static context.

Demo.java

1. class Demo
2. {
3. int num=100; //non-static variable
4. //static method
5. public static void main(String args[])
6. {
7. //trying to access non-static data member from static context
8. System.out.println(num);
9. }
10. }

Output:

Unary Operators in Java


In Java, the unary operator is an operator that can be used only with an operand. It is
used to represent the positive or negative value, increment/decrement the value by 1,
and complement a Boolean value. In this section, we will discuss the unary operator in
Java with examples and also understand the differences between i++ and i+=1.
There are five unary operators in Java:

o Unary Plus
o Unary Minus
o Increment Operator
o Decrement Operator
o Logical Complement Operator

The following table describes the short description of the unary operators.

Operator Name Symbol Description Exampl Equivalent


e Expression

Unary Plus + It is used to represent +a a


the positive value.

Unary Minus - It is used to represent -a -


the negative value.

Increment ++ It increments the value ++a a=a+1


Operator of a variable by 1. or
a++
Decrement -- It decrements the value --a a=a-1
Operator of a variable by 1. or
a--

Logical ! It inverts the value of a !true -


Complement boolean variable.
Operator

Unary Plus
It is used to represent positive values. Usually, we do not write the operator before the
operand. Hence, it is optional.

Syntax:

1. +(operand)

Example: x=+99 or x=99;

Unary Minus
It is used to convert a positive value into a negative one.

Syntax:

1. -(operand)

Increment Operator
It is used to increment the value of an operand by one. The operator is represented by a
pair of plus operators (++). The operator can be applied before or after an operand.

Pre-increment Operator: If an increment operator is written before (prefix) the


operand is known as pre-increment. In such a case, the value is first incremented by 1
and then taken for the computing purpose.

ADVERTISEMENT

Syntax:
1. ++operand

Example: Suppose x=9, then the value of ++x will be 10.

Post-increment Operator: If an increment operator is written after (postfix) the


operand is known as post-increment. In such a case, the value is first processed and
then incremented. It means the value that the variable holds first used for the
computing purpose and then incremented by 1.

Syntax:

1. operand++

Example: Suppose x=11, then the value of x++ will be 12.

Let's use the pre-increment and post-increment operators in a Java program.

PrePostIncrementExample.java

1. public class PrePostIncrementExample


2. {
3. public static void main(String args[])
4. {
5. int i = 10;
6. i++;
7. //prints 11
8. System.out.println(i);
9. ++i;
10. //prints 12
11. System.out.println(i);
12. //prints 13
13. System.out.println(++i);
14. //prints 13
15. System.out.println(i++);
16. //prints 14
17. System.out.println(i);
18. }
19. }

Output:

11
12
13
13
14

What is the difference between i++ and i+=1?


Both the expressions i++ and i+=1 evaluated the same result. But the only difference is
that i++ uses the increment operator (unary operator) and i+=1 uses the assignment
operator.

Another difference is that the expression i++ directly increments the value of i but the
expression i+=1 first converts into i=i+1 by the JVM and then executed.

ADVERTISEMENT

Decrement Operator
It is used to decrement the value of an operand by 1. The operator is represented by a
pair of minus operators (--). The operator can be applied before or after an operand.

Pre-decrement Operator: If a decrement operator is written before (prefix) the


operand is known as pre-decrement. In such a case, the value is first decremented by 1
and then used for the computing purpose.

Syntax:

1. --operand

Example: Suppose x=9, then the value of --x will be 8.

Post-decrement Operator: If a decrement operator is written after (postfix) the


operand is known as post-decrement. In such a case, the value is first used and then
decrements by 1.

Syntax:

1. operand--
Example: Suppose x=11, then the value of x-- will be 10.

Let's use the pre-decrement and post-decrement operators in a Java program.

PrePostDecrementExample.java

1. public class PrePostDecrementExample


2. {
3. public static void main(String args[])
4. {
5. int i = 10;
6. i--;
7. //prints 19
8. System.out.println(i);
9. --i;
10. //prints 18
11. System.out.println(i);
12. //prints 17
13. System.out.println(--i);
14. //prints 17
15. System.out.println(i--);
16. //prints 16
17. System.out.println(i);
18. }
19. }

Output:

19
18
17
17
16

Remember

o Nesting of increment or decrement operator is not allowed. For example:

1. int a=++(++b); //not allowed


o Never use unary operators with the final
o The expressions ++x and x++ is the same as x=x+1 and the expressions - -x and
x- - is the same as x=x-1.

Logical Complement Operator


It is used to reverse the value of an operand. It means if an operand has value true, the
complement if the operator will be false and vice-versa. It is represented by the
exclamatory symbol (!).

Syntax:

1. !(operand)

Example: flag=!true;

Example of Unary Operator


In the following example, we have used all the unary operators that we have discussed
above.

UnaryOperatorExample.java

1. public class UnaryOperatorExample


2. {
3. public static void main(String[] args)
4. {
5. //using unary plus operator
6. //represents the positive value of the variable number
7. //it is optional
8. int number = +76;
9. //prints the positive value of the variable number
10. System.out.println(number);
11.
12. //using unary minus operator
13. //represents the negative value of the variable number
14. number = -number;
15. //prints the negative value of the variable number
16. System.out.println(number);
17. int a=20;
18. //increments the value of the variable by 1
19. a++;
20. //prints the incremented value of the variable
21. System.out.println(a);
22. //decrements the value of the variable by 1
23. a--;
24. //prints the decremented value of the variable
25. System.out.println(a);
26. //declaring a boolean variable
27. boolean flag = false;
28. //prints the value of success variable
29. System.out.println(flag);
30. //prints the complement of the success variable
31. System.out.println(!flag);
32. }
33. }

Output:

76
-76
21
20
false
true

What is Advance Java?


The dictionary meaning of advance is a forward movement or a development or
improvement and the meaning of improve means thing that makes something better.
All in all, we have to improve our basic knowledge to master in that particular field.
Java is divided into two parts i.e. Core Java (J2SE) and Advanced Java (JEE). The core
Java part covers the fundamentals (data types, functions, operators, loops, thread,
exception handling, etc.) of the Java programming language. It is used to develop
general purpose applications. Whereas Advanced Java covers the standard concepts
such as database connectivity, networking, Servlet, web-services, etc. In this section, we
will discuss what is advance Java, its benefit, uses, topics of advance Java, and
the difference between core Java and advance Java.

Advance Java
It is a part of Java programming language. It is an advanced technology or advance
version of Java specially designed to develop web-based, network-centric or enterprise
applications. It includes the concepts like Servlet, JSP, JDBC, RMI, Socket programming,
etc. It is a specialization in specific domain.

Most of the applications developed using advance Java uses tow-tier architecture i.e.
Client and Server. All the applications that runs on Server can be considered as advance
Java applications.

Why advance Java?

o It simplifies the complexity of a building n-tier application.


o Standardizes and API between components and application sever container.
o JEE application Server and Containers provides the framework services.

Benefits of Advance Java


The four major benefits of advance Java that are, network centric, process simplification,
and futuristic imaging standard.

o JEE (advance Java) provides libraries to understand the concept of Client-Server


architecture for web- based applications.
o We can also work with web and application servers such as Apache
Tomcat and Glassfish Using these servers, we can understand the working of
HTTP protocol. It cannot be done in core Java.
o It is also important understand the advance Java if you are dealing with trading
technologies like Hadoop, cloud-native and data science.
o It provides a set of services, API and protocols, that provides the functionality
which is necessary for developing multi-tiered application, web-based
application.
o There is a number of advance Java frameworks like, Spring, Hibernate,
Struts, that enables us to develop secure transaction-based web applications
such as banking application, inventory management application.

Difference between Core Java and Advance


Java

Criteria Core Java Advance Java

Used for It is used to develop general It is used to develop web-based


purpose application. applications.

Purpose It does not deal with database, It deals with socket programming,
socket programming, etc. DOM, and networking applications.

Architectur It is a single tier architecture. It is a mute-tier architecture.


e

Edition It is a Java Standard Edition. It is a Java Enterprise Edition.

Package It provides java.lang.* package. It provides java.servlet.* package.

Advance Java Topics or Syllabus


1. Basics of a Web application

o What is a web application?


o What is a web client and web server?
o How do client and server communicate?
o HTTP protocol basics
o HTML language basics
o What is a TCP/IP port, URL?
o Need for a Web Container

2. Web Container and Web Application Project Set up

o To set up Tomcat Container on a machine


o To set up a Servlets JSP project in Eclipse
o To configure dependency of Servlet JSP APIs
o Web application project structure

3. Servlets

o What are Servlets?


o What can they do? Why are they needed?
o How do Servlets look in code?
o HTTP Methods; GET, POST, PUT, DELETE, TRACE, OPTIONS
o GET/POST request; differences between the two
o Servlet Lifecycle
o Servlet Context and Servlet Config
o Forwarding and Redirection of requests

4. Session Management

o What is a session?
o Why is it required?
o How to get a session?
o Session information passing between client and server
o Session information passing mechanisms - Cookies, Rewriting
o How to destroy a session

5. JSPs

ADVERTISEMENT

o Introduction to JSP and need for JSPs


o Basic HTML tags
o JSP Lifecycle

6. JSP Elements

o Scriptlets
o Expressions
o Declarations
o Significance of above elements and fitment into the JSP Lifecycle
o What are Directives in JSP?
o Page Directive
o Include Directives
o Taglib Directive

7. JSP Tag library

o JSP Standard Actions


o Expression Language
o JSTL basics and it's usage
o Need for Custom Tag Library
o Custom Tag Library implementation

Struts Framework (version 2.x)


1. Basics of MVC

o What is MVC?
o MVC Type1 and Type2 architecture
o Why Struts framework?
o Struts 1 overview
o Struts 1 and Struts 2 comparison

2. Struts 2 Architecture

o Architecture Diagram explanation of following components:


o Components of Model, Views and Controller in Struts Framework
o Interceptors
o Model/Action classes
o Value Stack
o OGNL
o Introduction to configurations; framework and application architecture
o Declarative and Annotations configuration approaches

3. Struts 2 set up and first Action class

o Download JAR files


o Struts 2 project build up and Configuration files
o To build Action class
o To intercept an HTTP request via Struts2 framework using Action class
o Defining data and business logic in Action class
o Preparing and Forwarding control to Views

4. Struts 2 Interceptors

o What are Interceptors


o Responsibilities of an Interceptor
o Mechanism of Interceptor calling in Struts 2
o Defining Interceptors
o Defining Interceptor stacks
o Defining Custom Interceptors

5. Struts 2 Tag Library

o Introduction to tag library of Struts 2 and it's usage

6. Struts 2 Validations

o Validations using Validateable interface


o Workflow interceptor mechanism for validations
o Validations using Validateable interface
o Validation Framework introduction and architecture
o Validating user input with above two mechanisms

7. Struts 2 Tiles Frameworks

o Introduction to Tiles in a page


o Struts2 Tiles framework introduction
o Defining tiles.xml file
o Configuring pages for tiles
o A complete Tiles example with Struts2

Hibernate Framework (version 3.x)


1. Introduction

ADVERTISEMENT

o What is ORM principle?


o Why ORM?
o ORM implementations

2. Hibernate Architecture

o Introduction to Hibernate
o Hibernate Architecture
o What are Persistent classes?

3. Hibernate CRUD

o Setting up Hibernate project


o Configuring all JARs and XML files
o Setting up connection to DB using Hibernate
o Performing basic CRUD operations using Hibernate API
o Object Identity; Generator type classes
o Using SQL with Hibernate
o Using HQL
o Using Criteria queries

ADVERTISEMENT
ADVERTISEMENT

4. Mapping Collections and Associations

o To define sets, mas, lists in Hibernate


o Association Mappings:
1. One to one
2. One to many
3. Many to one
4. Many to many
o Hibernate Caching
o What is caching?
o What are the types of caching in Hibernate?
o Explanation of various caching mechanisms in Hibernate

5. Using Hibernate Annotations

o Sample example of using Hibernate Annotations

Spring Framework (version 3.x)


1. Introduction to spring

o What is Spring?
o Spring Architecture explanation and all it's components

2. Introduction to all modules of Spring

o Spring Bean Factory


o Spring Application Context
o Spring DI
o Spring Integration; Spring messaging, Spring JMS
o Spring MVC
o Spring DAO

3. Setting up spring

o Setting up of Spring framework


o Download JARs
o Configure XML files

4. Dependency Injection

o What is Dependency Injection?


o How is it implemented using Spring Framework?
o Bean Wiring mechanisms in Spring

5. Spring AOP

o What is Spring AOP?


o Implementation of Spring AOP

Spring Boot Framework (Version 2.x)


1. Introduction

o Spring Boot Introduction


o Spring Boot Version
o Spring vs Spring Boot vs Spring MVC
o Spring Boot Architecture

2. Creating Project

o Spring Initializr
o Download & Install STS IDE
o Spring Boot Example
o Spring Boot CLI
o Spring Boot Example-STS

3. Project Components

o Annotations
o Dependency Management
o Application Properties
o Starters
o Starter Parent
o Starter Web
o Starter Data JPA
o Starter Actuator
o Starter Test
o Devtools
o Multi Module Project
o Packaging
o Auto-Configuration

4. Tool Suite

o Hello World Example


o Project Deployment Using Tomcat

5. Spring Boot AOP

o What is AOP?
o AOP Before Advice
o AOP After Advice
o AOP Around Advice
o After Returning Advice
o After Throwing Advice
6. Spring Boot Database

o JPA
o JDBC
o H2 Database
o Crud Operations

7. Spring Boot View

o Thymeleaf View

8. Spring Boot Caching

o What is Caching?
o Cache Provider
o EhCaching

9. Spring Boot Misc

o Run Spring Boot Application


o Changing Port
o Spring Boot Rest Example

Web Services: REST and SOAP

o Logging Framework: Splunk, Log4J, SLF4j


o Version-control system + repository hosting service: Git + Github
Bitwise Operator in Java
In Java, an operator is a symbol that performs the specified operations. In this section,
we will discuss only the bitwise operator and its types with proper examples.

Types of Bitwise Operator


There are six types of the bitwise operator in Java:

o Bitwise AND
o Bitwise exclusive OR
o Bitwise inclusive OR
o Bitwise Compliment
o Bit Shift Operators

Operators Symbol Uses

Bitwise AND & op1 & op2

Bitwise exclusive OR ^ op1 ^ op2

Bitwise inclusive OR | op1 | op2

Bitwise Compliment ~ ~ op

Bitwise left shift << op1 << op2

Bitwise right shift >> op1 >> op2

Unsigned Right Shift Operator >>> op >>> number of places to shift

Let's explain the bitwise operator in detail.


Bitwise AND (&)
It is a binary operator denoted by the symbol &. It returns 1 if and only if both bits are
1, else returns 0.

Let's use the bitwise AND operator in a Java program.

BitwiseAndExample.java

1. public class BitwiseAndExample


2. {
3. public static void main(String[] args)
4. {
5. int x = 9, y = 8;
6. // bitwise and
7. // 1001 & 1000 = 1000 = 8
8. System.out.println("x & y = " + (x & y));
9. }
10. }

Output

x & y = 8

Bitwise exclusive OR (^)


It is a binary operator denoted by the symbol ^ (pronounced as caret). It returns 0 if
both bits are the same, else returns 1.
Let's use the bitwise exclusive OR operator in a Java program.

BitwiseXorExample.java

1. public class BitwiseXorExample


2. {
3. public static void main(String[] args)
4. {
5. int x = 9, y = 8;
6. // bitwise XOR
7. // 1001 ^ 1000 = 0001 = 1
8. System.out.println("x ^ y = " + (x ^ y));
9. }
10. }

Output

x ^ y = 1

Bitwise inclusive OR (|)


It is a binary operator denoted by the symbol | (pronounced as a pipe). It returns 1 if
either of the bit is 1, else returns 0.

Let's use the bitwise inclusive OR operator in a Java program.


BitwiseInclusiveOrExample.java

1. public class BitwiseInclusiveOrExample


2. {
3. public static void main(String[] args)
4. {
5. int x = 9, y = 8;
6. // bitwise inclusive OR
7. // 1001 | 1000 = 1001 = 9
8. System.out.println("x | y = " + (x | y));
9. }
10. }

Output

x | y = 9

Bitwise Complement (~)


It is a unary operator denoted by the symbol ~ (pronounced as the tilde). It returns the
inverse or complement of the bit. It makes every 0 a 1 and every 1 a 0.

Let's use the bitwise complement operator in a Java program.

BitwiseComplimentExample.java

1. public class BitwiseComplimentExample


2. {
3. public static void main(String[] args)
4. {
5. int x = 2;
6. // bitwise compliment
7. // ~0010= 1101 = -3
8. System.out.println("~x = " + (~x));
9. }
10. }

Output

~x = -3

Bit Shift Operators


Shift operator is used in shifting the bits either right or left. We can use shift operators if
we divide or multiply any number by 2. The general format to shift the bit is as follows:

ADVERTISEMENT

1. variable << or >> number of places to shift;

For example, if a=10

1. a>>2; //shifts two bits


2. a>>4; //shifts 4 bits

Java provides the following types of shift operators:

o Signed Right Shift Operator or Bitwise Right Shift Operator


o Unsigned Right Shift Operator
o Signed Left Shift Operator or Bitwise Left Shift Operator

Note: Java does not support the unsigned left shift operator (<<<).

Signed Right Shift Operator (>>)


ADVERTISEMENT

ADVERTISEMENT

The signed right shift operator shifts a bit pattern of a number towards the right with a
specified number of positions and fills 0. The operator is denoted by the symbol >>. It
also preserves the leftmost bit (sign bit). If 0 is presented at the leftmost bit, it means
the number is positive. If 1 is presented at the leftmost bit, it means the number
is negative.
In general, if we write a>>n, it means to shift the bits of a number toward the right with
a specified position (n). In the terms of mathematics, we can represent the signed right
shift operator as follows:

Note: When we apply right shift operator on a positive number, we get the positive number
in the result also. Similarly, when we apply right shift operator on a negative number, we get
the negative number in the result also.

Example: Apply the signed right shift operator with specified positions 4 if x = 256
and x = -256.

If x = 256

256 >> 4

256/24 = 16

If x = -256

-256 >> 4

-256/24 = -16

In the above example, we have observed that after shifting the operator 256 converted
into 16 and -256 converted into -16.

Let's create a Java program and implement the left shift operator.

SignedRightShiftOperatorExample.java

1. public class SignedRightShiftOperatorExample


2. {
3. public static void main(String args[])
4. {
5. int x = 50;
6. System.out.println("x>>2 = " + (x >>2));
7. }
8. }
ADVERTISEMENT

Output

x>>2 = 12

Signed Left Shift Operator (<<)


The signed left shift operator (<<) shifts a bit pattern to the left. It is represented by the
symbol <<. It also preserves the leftmost bit (sign bit). It does not preserve the sign bit.

In general, if we write a<<n, it means to shift the bits of a number toward the left with
specified position (n). In the terms of mathematics, we can represent the signed right
shift operator as follows:

Example 1: What will be the result after shifting a<<3. The value of a is 20.

Representation of 20 in binary is = 00010100

After performing the left shift operator, we get:

a << 3 = 10100000 (last three bits are the filled bits)

a << 3 = 160

Let's check the result by using the formula.

20 << 3
20*23 = 20*8 = 160

Example 2: What will be the result after shifting a<<2. The value of a is -10.

Representation of -10 in binary is = 11110110

ADVERTISEMENT

a<<2 = 11011000 = -40

Let's check the result by using the formula.

-10 << 3

-10*22 = -10*4 = -40

Let's create a Java program and implement the signed left shift operator.

SignedLeftShiftOperatorExample.java

1. public class SignedLeftShiftOperatorExample


2. {
3. public static void main(String args[])
4. {
5. int x = 12;
6. System.out.println("x<<1 = " + (x << 1));
7. }
8. }

Output

x<<1 = 24

Unsigned Right Shift Operator (>>>)


It shifts a zero at the leftmost position and fills 0. It is denoted by the symbol >>>. Note
that the leftmost position after >> depends on the sign bit. It does not preserve the sign
bit.

Example: If a=11110000 and b=2, find a>>>b?


a >>> b = 11110000 >>> 2 = 00111100

The left operand value is moved right by the number of bits specified by the right
operand and the shifted bits are filled up with zeros. Excess bits shifted off to the right
are discarded.

Therefore, before shifting the bits the decimal value of a is 240, and after shifting the
bits the decimal value of a is 60.

Let's create a Java program and use the unsigned right shift operator.

UnsignedRightShiftOperatorExample.java

1. public class UnsignedRightShiftOperatorExample


2. {
3. public static void main(String args[])
4. {
5. int x = 20;
6. System.out.println("x>>>2 = " + (x >>>2));
7. }
8. }

Output

x>>>2 = 5
SOLID Principles Java
In Java, SOLID principles are an object-oriented approach that are applied to software structure
design. It is conceptualized by Robert C. Martin (also known as Uncle Bob). These five
principles have changed the world of object-oriented programming, and also changed the way of
writing software. It also ensures that the software is modular, easy to understand, debug, and
refactor. In this section, we will discuss SOLID principles in Java with proper example.

The word SOLID acronym for:

o Single Responsibility Principle (SRP)


o Open-Closed Principle (OCP)
o Liskov Substitution Principle (LSP)
o Interface Segregation Principle (ISP)
o Dependency Inversion Principle (DIP)
Let's explain the principles one by one in detail.

Single Responsibility Principle


The single responsibility principle states that every Java class must perform a single
functionality. Implementation of multiple functionalities in a single class mashup the code and
if any modification is required may affect the whole class. It precise the code and the code can be
easily maintained. Let's understand the single responsibility principle through an example.

Suppose, Student is a class having three methods namely printDetails(),


calculatePercentage(), and addStudent(). Hence, the Student class has three
responsibilities to print the details of students, calculate percentages, and database. By using the
single responsibility principle, we can separate these functionalities into three separate classes to
fulfill the goal of the principle.

Student.java

1. public class Student


2. {
3. public void printDetails();
4. {
5. //functionality of the method
6. }
7. pubic void calculatePercentage();
8. {
9. //functionality of the method
10. }
11. public void addStudent();
12. {
13. //functionality of the method
14. }
15. }

The above code snippet violates the single responsibility principle. To achieve the goal of the
principle, we should implement a separate class that performs a single functionality only.
Student.java

1. public class Student


2. {
3. public void addStudent();
4. {
5. //functionality of the method
6. }
7. }

PrintStudentDetails.java

1. public class PrintStudentDetails


2. {
3. public void printDetails();
4. {
5. //functionality of the method
6. }
7. }

Percentage.java

ADVERTISEMENT
ADVERTISEMENT

1. public class Percentage


2. {
3. public void calculatePercentage();
4. {
5. //functionality of the method
6. }
7. }

Hence, we have achieved the goal of the single responsibility principle by separating the
functionality into three separate classes.

Open-Closed Principle
The application or module entities the methods, functions, variables, etc. The open-closed
principle states that according to new requirements the module should be open for
extension but closed for modification. The extension allows us to implement new
functionality to the module. Let's understand the principle through an example.

Suppose, VehicleInfo is a class and it has the method vehicleNumber() that returns the
vehicle number.

VehicleInfo.java

1. public class VehicleInfo


2. {
3. public double vehicleNumber(Vehicle vcl)
4. {
5. if (vcl instanceof Car)
6. {
7. return vcl.getNumber();
8. if (vcl instanceof Bike)
9. {
10. return vcl.getNumber();
11. }
12. }

If we want to add another subclass named Truck, simply, we add one more if statement that
violates the open-closed principle. The only way to add the subclass and achieve the goal of
principle by overriding the vehicleNumber() method, as we have shown below.

VehicleInfo.java

1. public class VehicleInfo


2. {
3. public double vehicleNumber()
4. {
5. //functionality
6. }
7. }
8. public class Car extends VehicleInfo
9. {
10. public double vehicleNumber()
11. {
12. return this.getValue();
13. }
14. public class Car extends Truck
15. {
16. public double vehicleNumber()
17. {
18. return this.getValue();
19. }

Similarly, we can add more vehicles by making another subclass extending from the vehicle
class. the approach would not affect the existing application.

Liskov Substitution Principle


The Liskov Substitution Principle (LSP) was introduced by Barbara Liskov. It applies to
inheritance in such a way that the derived classes must be completely substitutable for
their base classes. In other words, if class A is a subtype of class B, then we should be able to
replace B with A without interrupting the behavior of the program.

It extends the open-close principle and also focuses on the behavior of a superclass and its
subtypes. We should design the classes to preserve the property unless we have a strong reason
to do otherwise. Let's understand the principle through an example.

Student.java

ADVERTISEMENT

1. public class Student


2. {
3. private double height;
4. private double weight;
5. public void setHeight(double h)
6. {
7. height = h;
8. }
9. public void setWeight(double w)
10. {
11. weight= w;
12. }
13. ...
14. }
15. public class StudentBMI extends Student
16. {
17. public void setHeight(double h)
18. {
19. super.setHeight(h);
20. super.setWeight(w);
21. }
22. public void setWeight(double h)
23. {
24. super.setHeight(h);
25. super.setWeight(w);
26. }
27. }

The above classes violated the Liskov substitution principle because the StudentBMI class has
extra constraints i.e. height and weight that must be the same. Therefore, the Student class (base
class) cannot be replaced by StudentBMI class (derived class).

Hence, substituting the class Student with StudentBMI class may result in unexpected behavior.

Interface Segregation Principle


ADVERTISEMENT
ADVERTISEMENT

The principle states that the larger interfaces split into smaller ones. Because the implementation
classes use only the methods that are required. We should not force the client to use the methods
that they do not want to use.

The goal of the interface segregation principle is similar to the single responsibility principle.
Let's understand the principle through an example.
Suppose, we have created an interface named Conversion having three
methods intToDouble(), intToChar(), and charToString().

1. public interface Conversion


2. {
3. public void intToDouble();
4. public void intToChar();
5. public void charToString();
6. }

The above interface has three methods. If we want to use only a method intToChar(), we have no
choice to implement the single method. To overcome the problem, the principle allows us to split
the interface into three separate ones.

1. public interface ConvertIntToDouble


2. {
3. public void intToDouble();
4. }
5. public interface ConvertIntToChar
6. {
7. public void intToChar();
8. }
9. public interface ConvertCharToString
10. {
11. public void charToString();
12. }

Now we can use only the method that is required. Suppose, we want to convert the integer to
double and character to string then, we will use only the
methods intToDouble() and charToString().

1. public class DataTypeConversion implements ConvertIntToDouble, ConvertCharToString


2. {
3. public void intToDouble()
4. {
5. //conversion logic
6. }
7. public void charToString()
8. {
9. //conversion logic
10. }
11. }

Dependency Inversion Principle


The principle states that we must use abstraction (abstract classes and interfaces) instead of
concrete implementations. High-level modules should not depend on the low-level module but
both should depend on the abstraction. Because the abstraction does not depend on detail but the
detail depends on abstraction. It decouples the software. Let's understand the principle through
an example.

1. public class WindowsMachine


2. {
3. //functionality
4. }

It is worth, if we have not keyboard and mouse to work on Windows. To solve this problem, we
create a constructor of the class and add the instances of the keyboard and monitor. After adding
the instances, the class looks like the following:

1. public class WindowsMachine


2. {
3. public final keyboard;
4. public final monitor;
5. public WindowsMachine()
6. {
7. monitor = new monitor(); //instance of monitor class
8. keyboard = new keyboard(); //instance of keyboard class
9. }
10. }

Now we can work on the Windows machine with the help of a keyboard and mouse. But we still
face the problem. Because we have tightly coupled the three classes together by using the new
keyword. It is hard o test the class windows machine.

To make the code loosely coupled, we decouple the WindowsMachine from the keyboard by
using the Keyboard interface and this keyword.

Keyboard.java

1. public interface Keyboard


2. {
3. //functionality
4. }

WindowsMachine.java

1. public class WindowsMachine


2. {
3. private final Keyboard keyboard;
4. private final Monitor monitor;
5. public WindowsMachine(Keyboard keyboard, Monitor monitor)
6. {
7. this.keyboard = keyboard;
8. this.monitor = monitor;
9. }
10. }
In the above code, we have used the dependency injection to add the keyboard dependency in the
WindowsMachine class. Therefore, we have decoupled the classes.

Why should we use SOLID principles?


o It reduces the dependencies so that a block of code can be changed without
affecting the other code blocks.
o The principles intended to make design easier, understandable.
o By using the principles, the system is maintainable, testable, scalable, and
reusable.
o It avoids the bad design of the software.

Next time when you design software, keeps these five principles in mind. By applying
these principles, the code will be much more clear, testable, and expendable.
Type Casting in Java
In Java, type casting is a method or process that converts a data type into another data
type in both ways manually and automatically. The automatic conversion is done by the
compiler and manual conversion performed by the programmer. In this section, we will
discuss type casting and its types with proper examples.

Type casting
Convert a value from one data type to another data type is known as type casting.

Types of Type Casting


There are two types of type casting:

ADVERTISEMENT
ADVERTISEMENT

o Widening Type Casting


o Narrowing Type Casting

Widening Type Casting


Converting a lower data type into a higher one is called widening type casting. It is also
known as implicit conversion or casting down. It is done automatically. It is safe
because there is no chance to lose data. It takes place when:
o Both data types must be compatible with each other.
o The target type must be larger than the source type.

1. byte -> short -> char -> int -> long -> float -> double

For example, the conversion between numeric data type to char or Boolean is not done
automatically. Also, the char and Boolean data types are not compatible with each other.
Let's see an example.

WideningTypeCastingExample.java

1. public class WideningTypeCastingExample


2. {
3. public static void main(String[] args)
4. {
5. int x = 7;
6. //automatically converts the integer type into long type
7. long y = x;
8. //automatically converts the long type into float type
9. float z = y;
10. System.out.println("Before conversion, int value "+x);
11. System.out.println("After conversion, long value "+y);
12. System.out.println("After conversion, float value "+z);
13. }
14. }

Output

Before conversion, the value is: 7


After conversion, the long value is: 7
After conversion, the float value is: 7.0

In the above example, we have taken a variable x and converted it into a long type. After
that, the long type is converted into the float type.

Narrowing Type Casting


Converting a higher data type into a lower one is called narrowing type casting. It is
also known as explicit conversion or casting up. It is done manually by the
programmer. If we do not perform casting then the compiler reports a compile-time
error.

1. double -> float -> long -> int -> char -> short -> byte

Let's see an example of narrowing type casting.

In the following example, we have performed the narrowing type casting two times.
First, we have converted the double type into long data type after that long data type is
converted into int type.

NarrowingTypeCastingExample.java

1. public class NarrowingTypeCastingExample


2. {
3. public static void main(String args[])
4. {
5. double d = 166.66;
6. //converting double data type into long data type
7. long l = (long)d;
8. //converting long data type into int data type
9. int i = (int)l;
10. System.out.println("Before conversion: "+d);
11. //fractional part lost
12. System.out.println("After conversion into long type: "+l);
13. //fractional part lost
14. System.out.println("After conversion into int type: "+i);
15. }
16. }

Output

Before conversion: 166.66


After conversion into long type: 166
After conversion into int type: 166
Conditional Operator in Java
In Java, conditional operators check the condition and decides the desired result on
the basis of both conditions. In this section, we will discuss the conditional operator in
Java.

Types of Conditional Operator


There are three types of the conditional operator in Java:

ADVERTISEMENT

ADVERTISEMENT

o Conditional AND
o Conditional OR
o Ternary Operator

Operator Symbol

Conditional or Logical &&


AND

Conditional or Logical ||
OR

Ternary Operator ?:
Conditional AND
The operator is applied between two Boolean expressions. It is denoted by the two AND
operators (&&). It returns true if and only if both expressions are true, else returns false.

Expression Expression2 Expression1 &&


1 Expression2

True False False

False True False

False False False

True True True

Conditional OR
The operator is applied between two Boolean expressions. It is denoted by the two OR
operator (||). It returns true if any of the expression is true, else returns false.

Expression1 Expression2 Expression1 ||


Expression2

True True True

True False True

False True True

False False False


Let's create a Java program and use the conditional operator.

ConditionalOperatorExample.java

1. public class ConditionalOperatorExample


2. {
3. public static void main(String args[])
4. {
5. int x=5, y=4, z=7;
6. System.out.println(x>y && x>z || y<z);
7. System.out.println((x<z || y>z) && x<y);
8. }
9. }

Output

true
false

Ternary Operator
The meaning of ternary is composed of three parts. The ternary operator (? :) consists
of three operands. It is used to evaluate Boolean expressions. The operator decides
which value will be assigned to the variable. It is the only conditional operator that
accepts three operands. It can be used instead of the if-else statement. It makes the
code much more easy, readable, and shorter.

Note: Every code using an if-else statement cannot be replaced with a ternary operator.

Syntax:

1. variable = (condition) ? expression1 : expression2

The above statement states that if the condition returns true, expression1 gets
executed, else the expression2 gets executed and the final result stored in a variable.

ADVERTISEMENT
Let's understand the ternary operator through the flowchart.
TernaryOperatorExample.java

1. public class TernaryOperatorExample


2. {
3. public static void main(String args[])
4. {
5. int x, y;
6. x = 20;
7. y = (x == 1) ? 61: 90;
8. System.out.println("Value of y is: " + y);
9. y = (x == 20) ? 61: 90;
10. System.out.println("Value of y is: " + y);
11. }
12. }

Output

Value of y is: 90
Value of y is: 61

Let's see another example that evaluates the largest of three numbers using the ternary
operator.

LargestNumberExample.java

1. public class LargestNumberExample


2. {
3. public static void main(String args[])
4. {
5. int x=69;
6. int y=89;
7. int z=79;
8. int largestNumber= (x > y) ? (x > z ? x : z) : (y > z ? y : z);
9. System.out.println("The largest numbers is: "+largestNumber);
10. }
11. }

Output
The largest number is: 89

In the above program, we have taken three variables x, y, and z having the values 69, 89,
and 79, respectively. The expression (x > y) ? (x > z ? x : z) : (y > z ? y : z) evaluates the
largest number among three numbers and store the final result in the variable
largestNumber. Let's understand the execution order of the expression.

ADVERTISEMENT

First, it checks the expression (x > y). If it returns true the expression (x > z ? x : z) gets
executed, else the expression (y > z ? y : z) gets executed.

When the expression (x > z ? x : z) gets executed, it further checks the condition x > z.
If the condition returns true the value of x is returned, else the value of z is returned.

When the expression (y > z ? y : z) gets executed it further checks the condition y > z. If
the condition returns true the value of y is returned, else the value of z is returned.

Therefore, we get the largest of three numbers using the ternary operator.

You might also like