Java Architecture
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.
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.
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 works as a mediator between Java method calls and native libraries.
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.
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.
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.
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.
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.
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
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
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:
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:
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.
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:
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
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.
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:
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.
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.
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.
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.
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:
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:
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:
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:
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:
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:
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. 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:
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
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
Duration 18:10
Loaded: 0.37%
Â
Fullscreen
Backward Skip 10sPlay VideoForward Skip 10s
The properties of the static class are:
StaticClassExample.java
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.
FinalClassExample.java
Output:
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.
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:
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.
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:
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:
SingletonClassExample.java
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.
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:
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. }
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:
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. }
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. }
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
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:
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.
boolean Boolean
int Integer
char Character
double Double
float Float
long Long
byte Byte
short Short
WrapperClassExample.java
Output:
The declaration of marker interface is the same as interface in Java but the interface
must be empty. For example:
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.
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.
o Cloneable Interface
o Serializable Interface
o Remote Interface
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:
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.
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:
Example of Deserialization
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
1. import java.rmi.*;
2. public interface AddAll extends Remote
3. {
4. public int add(int r, int s)throws RemoteException;
5. }
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. }
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. }
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. }
CustomMarkerInterfaceExample.java
Output:
Car is a vehicle.
Yes, engine is working.
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
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.
1. PhoneNumber
2. PRICE
3. radius
4. a
5. a1
6. _phonenumber
7. $circumference
8. jagged_array
9. 12radius //invalid
Literal Type
23 int
9.86 double
"javatpoint" String
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 = , += , -= , *= , /= , %= , ^=
Logical && , ||
Bitwise &,|,^,~
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:
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.
We recommend you to set the maximum heap size between 512M to 1024M for small
and medium Java application.
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.
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
ADVERTISEMENT
ADVERTISEMENT
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.
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.
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.
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.
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:
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.
CountingSemaphoresExample.java
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.
BoundedSemaphoresExample.java
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.
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.
ADVERTISEMENT
BinarySemaphoresExample.java
ADVERTISEMENT
ADVERTISEMENT
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:
It creates a Semaphore with the given number of permits and the given fairness settings.
ADVERTISEMENT
Syntax:
1. public Semaphore(int permits, boolean fair)
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.
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.
Syntax:
Syntax:
1. public void release()
Syntax:
ADVERTISEMENT
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.
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.
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:
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:
Syntax:
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:
Syntax:
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:
Collectors.toList() Method: The method returns a Collector that collects the input
elements into a newly created List in an encounter method.
Syntax:
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:
Syntax:
ArrayToListExample5.java
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.
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
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.
ADVERTISEMENT
ADVERTISEMENT
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.
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
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.
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:
Let's create a Java program that clears the console using the platform-specific
command.
ClearScreenExample2.java
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:
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.
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.
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. 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. 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:
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,
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.
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:
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
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. }
o SimpleFormatter
o XMLFormatter
SimpleFormatter
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:
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.
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. }
The following table shows the level and the value corresponding to it.
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:
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.
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:
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.
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. }
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:
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.
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
Output:
Let's see another example to reverse a string using recursion.
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:
ADVERTISEMENT
ADVERTISEMENT
Both, float and double represents the floating-point numbers that store the decimal
values.
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.
The above declaration of float variable gives the compilation error. We can correct the
error by adding a suffix f or F.
Keyword used The float keyword is used to The double keyword is used to
define a float number. define a double-precision number.
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.
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
Output:
x/y = 0.33333334
DoubleDataTypeExample.java
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.
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.
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.
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.
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.
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.
EncapsulationDemo.java
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
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.
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.
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.
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.
Comparison It It
uses hashCode() or equals() m uses compare() or compareTo() m
ethod for comparison. ethod for comparison.
ADVERTISEMENT
ADVERTISEMENT
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
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.
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.
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. }
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
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.
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.
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
If the keyword static is prefixed before the function name, the function is called a static
function. It is often called a method.
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.
Syntax:
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:
ADVERTISEMENT
For example:
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:
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
Output:
ADVERTISEMENT
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:
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.
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)
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.
ADVERTISEMENT
Syntax:
1. ++operand
Syntax:
1. operand++
PrePostIncrementExample.java
Output:
11
12
13
13
14
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.
Syntax:
1. --operand
Syntax:
1. operand--
Example: Suppose x=11, then the value of x-- will be 10.
PrePostDecrementExample.java
Output:
19
18
17
17
16
Remember
Syntax:
1. !(operand)
Example: flag=!true;
UnaryOperatorExample.java
Output:
76
-76
21
20
false
true
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.
Purpose It does not deal with database, It deals with socket programming,
socket programming, etc. DOM, and networking applications.
3. Servlets
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
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
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
4. Struts 2 Interceptors
6. Struts 2 Validations
ADVERTISEMENT
2. Hibernate Architecture
o Introduction to Hibernate
o Hibernate Architecture
o What are Persistent classes?
3. Hibernate CRUD
ADVERTISEMENT
ADVERTISEMENT
o What is Spring?
o Spring Architecture explanation and all it's components
3. Setting up spring
4. Dependency Injection
5. Spring AOP
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 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
o Thymeleaf View
o What is Caching?
o Cache Provider
o EhCaching
o Bitwise AND
o Bitwise exclusive OR
o Bitwise inclusive OR
o Bitwise Compliment
o Bit Shift Operators
Bitwise Compliment ~ ~ op
BitwiseAndExample.java
Output
x & y = 8
BitwiseXorExample.java
Output
x ^ y = 1
Output
x | y = 9
BitwiseComplimentExample.java
Output
~x = -3
ADVERTISEMENT
Note: Java does not support the unsigned left shift operator (<<<).
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
Output
x>>2 = 12
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.
a << 3 = 160
20 << 3
20*23 = 20*8 = 160
Example 2: What will be the result after shifting a<<2. The value of a is -10.
ADVERTISEMENT
-10 << 3
Let's create a Java program and implement the signed left shift operator.
SignedLeftShiftOperatorExample.java
Output
x<<1 = 24
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
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.
Student.java
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
PrintStudentDetails.java
Percentage.java
ADVERTISEMENT
ADVERTISEMENT
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
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
Similarly, we can add more vehicles by making another subclass extending from the vehicle
class. the approach would not affect the existing application.
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
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.
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().
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.
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().
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:
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
WindowsMachine.java
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.
ADVERTISEMENT
ADVERTISEMENT
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
Output
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.
1. double -> float -> long -> int -> char -> short -> byte
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
Output
ADVERTISEMENT
ADVERTISEMENT
o Conditional AND
o Conditional OR
o Ternary Operator
Operator Symbol
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.
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.
ConditionalOperatorExample.java
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:
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
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
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.