Grokking The Java Developer Interview More Than 200 Questions To Crack The Java, Spring, SpringBoot & Hibernate Interview-1-200
Grokking The Java Developer Interview More Than 200 Questions To Crack The Java, Spring, SpringBoot & Hibernate Interview-1-200
Grokking The Java Developer Interview More Than 200 Questions To Crack The Java, Spring, SpringBoot & Hibernate Interview-1-200
JATIN ARORA
GROKKING THE JAVA DEVELOPER INTERVIEW
COPYRIGHT © 2020 BY JATIN ARORA.
All rights reserved. No part of this book may be reproduced,
distributed, or transmitted in any form or by any means, including
photocopying, recording or other electronic or mechanical
methods, without the prior written permission of the author,
except in the case of brief quotations embodied in critical reviews
and certain other non-commercial uses permitted by copyright
law.
For permission or any other information, contact me at:
[email protected]
Preface
Grokking The Java Developer Interview helps you to crack a Java, Spring &
Hibernate interview.
This book covers enough details of a Java/Spring topic that will surely help
the absolute beginners and if you are already familiar with Java & Spring,
then this book will help you to brush-up on the concepts.
The book has more than 200 questions that are frequently asked during an
interview for Java, Spring, SpringBoot & Hibernate profile. Some of the
important topics like Multi-threading, Collection framework, Singleton
Pattern, SpringBoot Annotations and many more are covered in detail. Most
of these topics are explained with code examples that will help you to
quickly grasp the concept.
This book contains a lot of code examples, most of the code snippets are
displayed in image format that you can zoom-in and out of. However, if
some image is not clearly visible on your device, you can also refer to the
GitHub repository for this book. The GitHub repo contains all of the snippets
shown in this book and it can be found at:
https://github.com/reachjatin/Grokking-The-Java-Developer-
Interview
Contact Information
I would love to hear from you.
For feedback or queries, you can contact me at
[email protected]
-Jatin Arora
Table of Contents
Preface
Acknowledgements
Question 1: What are the 4 pillars of OOPS?
Question 2: What is an abstract class?
Question 3: Does Abstract class have constructor?
Question 4: What is an Interface?
Question 5: Difference between abstract class and interface
Question 6: What to choose – interface or abstract class
Question 7: Why Java 8 has introduced default methods?
Question 8: Why Java 8 has introduced static methods?
Question 9: Why Java does not allow multiple inheritance?
Question 10: What are the rules for Method Overloading and Method
Overriding?
Question 11: Can we override final methods?
Question 12: Can constructors and private methods be overridden?
Question 13: What is final keyword and where it can be used?
Question 14: What is exception and exception handling?
Question 15: Difference between error and exception
Question 16: What are the different types of exceptions?
Question 17: How exception handling is done in java?
Question 18: Can we write a try block without catch block?
Question 19: How to handle multiple exceptions together?
Question 20: When finally block will not get executed
Question 21: Difference between throw and throws keyword. And discuss
Exception Propagation
Question 22: Exception handling w.r.t. method overriding
Question 23: Programs related to Exception handling and return keyword
Question 24: How to make your own custom exception class?
Question 25: How to make custom checked / unchecked exception?
Question 26: What happens when you throw an exception from finally
block?
Question 27: What will be Output of below program related to try-catch-
finally?
Question 28: Explain try-with-resources
Question 29: Why String is Immutable?
Question 30: What does the equals() method of String class do?
Question 31: Explain StringBuffer and StringBuilder
Question 32: Explain the output of below program related to equals()
method of StringBuilder
Question 33: When to use String/StringBuffer/StringBuilder
Question 34: Explain equals and hashcode contract
Question 35: What is Marker Interface?
Question 36: Can you write your own custom Marker interface?
Question 37: What is Comparable and Comparator?
Question 38: How to compare a list of Employees based on name and age
such that if name of the employee is same then sorting should be based on
age
Question 39: Difference between Comparable and Comparator
Question 40: Different methods of Object class
Question 41: What type of arguments are allowed in System.out.println()
method?
Question 42: Explain System.out.println() statement
Question 43: Explain Auto-boxing and Un-boxing
Question 44: Find the output of below program
Question 45: Can you pass primitive long value in switch statement?
Question 46: Explain static keyword in Java
Question 47: What is an Inner Class in Java, how it can be instantiated and
what are the types of Inner Classes?
Question 48: What is Constructor Chaining in java?
Question 49: What is init block?
Question 50: What is called first, constructor or init block?
Question 51: What is Variable shadowing and Variable hiding in Java?
Question 52: What is a constant and how we create constants in Java?
Question 53: Explain enum
Question 54: What is Cloneable?
Question 55: What is Shallow Copy and Deep Copy?
Question 56: What is Serialization and De-serialization?
Question 57: What is SerialVersionUID?
Question 58: Serialization scenarios with Inheritance
Question 59: Stopping Serialization and De-serialization
Question 60: What is Externalizable Interface?
Question 61: Externalizable with Inheritance
Question 62: Difference between Serializable and Externalizable
Question 63: How to make a class Immutable?
Question 64: Explain Class loaders in Java
Question 65: What is Singleton Design Pattern and how it can be
implemented?
Question 66: What are the different ways in which a Singleton Design
pattern can break and how to prevent that from happening?
Question 67: What are the different design patterns you have used in your
projects?
Question 68: Explain Volatile keyword in java
Question 69: What is Garbage Collection in Java, how it works and what are
the different types of Garbage Collectors?
Question 70: Explain Generics in Java
Question 71: What is Multi-threading?
Question 72: How to create a thread in Java?
Question 73: Which way of creating threads is better: Thread class or
Runnable interface
Question 74: What will happen if I directly call the run() method and not the
start() method to execute a thread
Question 75: Once a thread has been started can it be started again
Question 76: Why wait, notify and notifyAll methods are defined in the
Object class instead of Thread class
Question 77: Why wait(), notify(), notifyAll() methods must be called from
synchronized block
Question 78: difference between wait() and sleep() method
Question 79: join() method
Question 80: yield() method
Question 81: Tell something about synchronized keyword
Question 82: What is static synchronization?
Question 83: What will be output of below program where one
synchronized method is calling another synchronized method?
Question 84: Programs related to synchronized and static synchronized
methods
Question 85: What is Callable Interface?
Question 86: How to convert a Runnable to Callable
Question 87: Difference between Runnable and Callable
Question 88: What is Executor Framework in Java, its different types and
how to create these executors?
Question 89: Tell something about awaitTermination() method in executor
Question 90: Difference between shutdown() and shutdownNow() methods
of executor
Question 91: What is Count down latch in Java?
Question 92: What is Cyclic Barrier?
Question 93: Atomic classes
Question 94: What is Collection Framework?
Question 95: What is Collections?
Question 96: What is ArrayList?
Question 97: What is default size of ArrayList?
Question 98: Which data structure is used internally in an ArrayList?
Question 99: How add() method works internally or How the ArrayList grows
at runtime
Question 100: How to make an ArrayList as Immutable
Question 101: What is LinkedList?
Question 102: When to use ArrayList / LinkedList
Question 103: What is HashMap?
Question 104: Explain the internal working of put() and get() methods of
HashMap class and discuss HashMap collisions
Question 105: equals and hashCode method scenarios in HashMap when the
key is a custom class
Question 106: How to make a HashMap synchronized?
Question 107: What is Concurrent HashMap?
Question 108: What is HashSet class and how it works internally?
Question 109: Explain Java’s TreeMap
Question 110: Explain Java’s TreeSet
Question 111: Difference between fail-safe and fail-fast iterators
Question 112: Difference between Iterator and ListIterator
Question 113: Difference between Iterator.remove and Collection.remove()
Question 114: What is the difference between a Monolith and Micro-service
architecture?
Question 115: What is Dependency Injection in Spring?
Question 116: What are the different types of Dependency Injection?
Question 117: Difference between Constructor and Setter injection
Question 118: What is @Autowired annotation?
Question 119: What is the difference between BeanFactory and
ApplicationContext?
Question 120: Explain the life-cycle of a Spring Bean
Question 121: What are the different scopes of a Bean?
Question 122: What is the Default scope of a bean?
Question 123: What happens when we inject a prototype scope bean in a
singleton scope bean?
Question 124: How to inject a prototype scope bean in a singleton scope
bean?
Question 125: Explain Spring MVC flow
Question 126: What is the difference between <context:annotation-config>
and <context:component-scan>?
Question 127: What is the difference between Spring and SpringBoot?
Question 128: What is auto-configuration in SpringBoot?
Question 129: What are SpringBoot starters?
Question 130: What is @SpringBootApplication Annotation?
Question 131: Where does a Spring Boot application start from?
Question 132: How to remove certain classes from getting auto-configured
in SpringBoot?
Question 133: How to autowire a class which is in a package other than
SpringBoot application class’s package or any of its sub-packages
Question 134: What is application.properties file in a SpringBoot
application?
Question 135: How to configure the port number of a SpringBoot
application?
Question 136: Which jar builds our springboot application automatically
whenever we change some code just like a node.js application?
Question 137: What default embedded server is given in spring boot web
starter and how we can change the default embedded server to the one of
our choice
Question 138: Where should we put our html and javascript files in a spring
boot application?
Question 139: What are the different stereotype annotations?
Question 140: Difference between @Component, @Controller, @Service,
@Repository annotations?
Question 141: Difference between @Controller and @RestController
annotation
Question 142: What is @RequestMapping and @RequestParam annotation?
Question 143: How to define a Get or Post endpoint?
Question 144: Which annotation is used for binding the incoming json
request to the defined pojo class?
Question 145: What is @Qualifier annotation?
Question 146: What is @Transactional annotation?
Question 147: What is @ControllerAdvice annotation?
Question 148: What is @Bean annotation?
Question 149: Difference between @Component and @Bean
Question 150: How to do profiling in a SpringBoot application
Question 151: What is RestTemplate?
Question 152: What is Spring Data JPA?
Question 153: What is the difference between JPARepository,
CRUDRepository, PagingAndSortingRepository and which one you have used
in your applications?
Question 154: What is Spring AOP?
Question 155: Have you used Spring Security in your application
Question 156: What do you know about Spring Batch framework?
Question 157: Difference between SOAP and REST
Question 158: What is Restful api?
Question 159: What is a stateless object?
Question 160: What is the difference between Web Server and Application
Server?
Question 161: What do you know about CommandLineRunner and
ApplicationRunner?
Question 162: What do you know about Eureka Naming Server?
Question 163: What do you know about Zuul?
Question 164: What do you know about Zipkin?
Question 165: What do you know about Hysterix?
Question 166: What is JPA?
Question 167: What is Hibernate?
Question 168: Difference between JPA and Hibernate
Question 169: What is @Entity?
Question 170: How to give a name to a table in JPA?
Question 171: What is @Id, @GeneratedValue?
Question 172: How to use a custom database sequence in Hibernate to
generate primary key values?
Question 173: How to give names to the columns of a JPA Entity
Question 174: How to define a @OneToMany relationship between entities
Question 175: Why annotations should be imported from JPA and not from
Hibernate?
Question 176: What is the difference between get() and load() method of
Hibernate Session?
Question 177: What is the difference between save(), saveOrUpdate() and
persist() method of Hibernate Session?
Question 178: What is Session and SessionFactory in Hibernate?
Question 179: What is First Level and Second Level Cache in Hibernate?
Question 180: What is session.flush() method in Hibernate?
Question 181: How can we see the SQL query that gets generated by
Hibernate?
Question 182: What is Hibernate Dialect and why we need to configure it?
Question 183: What do you know about hibernate.hbm2ddl.auto property in
Hibernate?
Question 184: What is Maven?
Question 185: What is pom.xml?
Question 186: What is local repo and central repo?
Question 187: Where we define our local repo path?
Question 188: Where do we define proxies so that maven can download jars
from the internet in a corporate environment?
Question 189: Explain Maven build life-cycle
Question 190: What do you know about SQL Joins?
Question 191: Difference between TRUNCATE & DELETE statements
Question 192: Difference between Function and Stored Procedure
Question 193: What is DDL, DML statements?
Question 194: How to find the nth highest salary from Employee table
Question 195: Difference between UNION and UNION ALL commands in SQL
Question 196: Difference between Unique Key and Primary Key in SQL
Question 197: What is the difference between Primary and Foreign key in
SQL?
Question 198: What is the difference between clustered and non-clustered
index?
Question 199: What is the difference between WHERE and HAVING clause in
SQL
Question 200: How to change the gender column value from Male to Female
and Female to Male using single Update statement
Question 201: Find first 3 largest numbers in an array
Question 202: Move all negative numbers at the beginning of an array and
all positive numbers at the end
About the Author
Question 1: What are the 4 pillars of OOPS?
Answer: 4 pillars of OOPS are:
1. Abstraction
2. Encapsulation
3. Inheritance
4. Polymorphism
Let’s take a look at them:
Example:
Java Bean, where all data members are made private and you
define certain public methods to the outside world to access
them.
3. Inheritance: Using inheritance means defining a parent-child
relationship between classes, by doing so, you can reuse the
code that is already defined in the parent class. Code reusability
is the biggest advantage of Inheritance.
Java does not allow multiple inheritance through classes but it allows
it through interfaces.
4. Polymorphism: Poly means many and Morph means forms.
Polymorphism is the process in which an object or function takes
different forms. There are 2 types of Polymorphism :
Output:
Example 2:
Output:
Question 4: What is an Interface?
Answer:
- An interface in Java is a blueprint of a class. It has static
constants and abstract methods.
- Interface specify what a class must do but not how to do
- An interface is like defining a contract that is fulfilled by
implementing classes
- An interface is used to achieve full abstraction.
- All methods in an interface are public and abstract by default
and all variables declared in an interface are constants i.e.
public, static and final
- A class which implements an interface will have to provide
implementation of all the methods that are defined in the
interface
- A class can implement more than one interface, this is how
Java allows multiple inheritance.
- Since Java 8, we can have default and static methods in an
interface
Output:
Question 8: Why Java 8 has introduced static methods?
Answer: Consider an example where you want to define a utility class, what
you usually do is you define a class which contains static methods and then
you call these methods using class name. Now, Java 8 onwards you can do
the same thing using an Interface by giving only static methods inside your
interface. This way of using Interface for defining utility classes is better as it
helps in performance also, because using a class is more expensive
operation than using an interface.
Output:
Output:
Question 15: Difference between error and exception
Answer: Error: Errors in a program are irrecoverable, they indicate that
something severe has gone wrong in the application and the program gets
terminated in case of error occurrence e.g. running out of memory:
OutOfMemoryError, making too many recursive calls: StackOverflowError
etc.
Exception: Exceptions on the other hand are something that we can recover
from by handling them properly e.g.: trying to access a property/method
from a null object: NullPointerException, dividing an integer by zero:
ArithmeticException etc.
Suppose, your method is throwing more than one exception and you want
to perform some specific action based on the exception thrown, you should
use multiple catch blocks in this case.
Example using multiple catch blocks:
When using pipe (|) symbol:
Example: unchecked exception is thrown and it can be seen from the call
stack that it is propagated
Output:
Output:
Example: checked exceptions are not propagated down the call chain by
default,
You have to use throws keyword if you want to propagate the checked
exception, like
Notice in the above example that the checked exception is propagated and
now it is the responsibility of the caller method to either handle the
exception or throw it further. Below example is showing that the checked
exception is handled,
Output:
Output:
Example when parent class method does not declare an exception and
child class declares unchecked exception:
Output:
Example when child class overridden method throws same exception as the
parent one:
Output:
Example when parent class method declares an exception and child class
overridden method does not declare any exception:
Output:
One thing you should remember is, if you write anything after return
statement / throw exception statement, then that will give Compile time
error as ‘Unreachable code’.
Program 1:
Program 5:
Output:
Output:
Output:
ComparableDemo.java:
Output:
Output:
The output list is sorted based on employee’s names.
SalaryComparator.java:
ComparatorDemo.java:
Output:
ComparatorDemo.java:
Output:
Question 39: Difference between Comparable and
Comparator
Answer:
- Comparable interface can be used to provide single way of
sorting whereas Comparator interface is used to provide
multiple ways of sorting
- Comparable interface is present in ‘java.lang’ package whereas
Comparator interface is present in ‘java.util’ package
- For using Comparable, the class needs to implement
Comparable interface whereas for using Comparator, there is
no need to make changes in the class
- Comparable provides compareTo() method to sort elements,
whereas Comparator provides compare() method to sort
elements
- We can sort the list elements of Comparable type by using
Collections.sort(listObj) method, whereas to sort the list
elements of Comparator type, we have to provide a
Comparator object like, Collections.sort(listObj, Comparator)
At times, when you are using any third-party classes or the classes where
you are not the author of the class, then in that case Comparator is the only
choice to sort those objects
-Variable
-Method
-Block
-Nested
class
Static Variable: if any variable is declared as static, then it is known as ‘static
variable’. Only single copy of the variable gets created and all instances of
the class share same static variable. The static variable gets memory only
once in the class area at the time of class loading.
When to use static variable: static variables should be used to declare
common property of all objects as only single copy is created and shared
among all class objects, for example, the company name of employees etc.
Static Block: Static block gets executed exactly once when the class is first
loaded, use static block to initialize the static variables.
Compile Time Error comes when we try to access non-static member inside
static nested class:
If you have static members in your Static Inner class then there is no need to
create the inner class object:
Output:
Example:
Output:
Compile time error when static variable and static method is present in
Inner class:
There are 2 special types of Inner Classes:
Remember, you can only access the block level variables, and cannot change
them. You will get compile time error if you try to change them:
A variable whose value is not changed once initialized is called as effectively
final variable.
When to use:
Example 1 : Let’s understand this by an example, Suppose you are want to
return a list of employee class objects and they should be sorted based on
employee name, now for this you can write a comparator in a separate class
and pass its object inside the Collections.sort(list, comparatorObject)
Instead, you can use the anonymous inner class and you don’t have to
create a new class just for writing a comparator that you are not going to
use later on.
Program:
Employee.java:
AnonymousInnerDemo.java:
Output:
Example 3: You can use anonymous inner class in situations where you want
to override the parent class method without creating a separate child class:
Output:
Output:
super() example:
Output:
Example 2:
Output:
Example 3:
Output:
Order of execution:
- static blocks of super classes
- static blocks of the class
- init blocks of super classes
- constructors of super classes
- init blocks of the class
- constructors of the class
1. The code in static initialization block will be executed at
class load time (and yes, that means only once per class
load), before any instances of the class are constructed
and before any static methods are called.
2. The instance initialization block is actually copied by the
Java compiler into every constructor the class has. So, the
code in instance initialization block is
executed exactly before the code in constructor.
If you want to access instance variables then you can do so using ‘this’
keyword like below:
Example 2:
Output:
Variable Hiding: When the child and parent classes both have a variable
with the same name, the child class variable hides the parent class variable.
Example 1:
Output:
If you want to access parent’s class variable then you can do this using super
keyword:
Example 2:
Output:
Example 2:
Output:
Question 54: What is Cloneable?
Answer: Cloneable is an interface in Java which needs to be implemented by
a class to allow its objects to be cloned.
A class implements the Cloneable interface to indicate to the Object.clone()
method that it is legal for that method to make a field-for-field copy of
instances of that class.
If you try to Clone an object which doesn’t implement the Cloneable
interface, it will throw CloneNotSupportedException.
Here, we have created Employee object e1 with new keyword but then we
created another object Employee e2 which has the same reference as of e1.
So, any change in e2 object will reflect in e1 object and vice-versa.
Now, let’s implement Cloneable interface in our Employee class and invoke
the clone() method on e1 object to make its clone:
Program 2:
Output:
In the above example, we have only primitive types in our Employee class,
what if we have an object type i.e. another class object reference, see the
example below:
Program 3:
Can you guess the output of the last 2 sysout? Here is the output:
If you are surprised with the above output, then let me make it clear by
saying that, by default Object’s clone() method provide Shallow copy. This
brings us to the next interview question: What is shallow copy and deep
copy
Question 55: What is Shallow Copy and Deep Copy?
Answer: Shallow Copy: When we use the default implementation of clone()
method, a shallow copy of object is returned, meaning if the object that we
are trying to clone contains both primitive variables and non-primitive or
reference type variable, then only the object’s reference is copied not the
entire object itself.
Consider this with the example:
Employee object is having Company object as a reference, now when we
perform cloning on Employee object, then for primitive type variables,
cloning will be done i.e. new instances will be created and copied to the
cloned object but for non-primitive i.e. Company object, only the object’s
reference will be copied to the cloned object. It simply means Company
object will be same in both original and cloned object, changing the value in
one will change the value in other and vice-versa.
Now, if you want to clone the Company object also, so that your original and
cloned Employee object will be independent of each other, then you have to
perform Deep Copy.
Deep Copy: in Deep copy, the non-primitive types are also cloned to make
the original and cloned object fully independent of each other.
Program 1:
Output:
In above example, we have overridden the clone method in our employee
class and we called the clone method on mutable company object.
We can also use Copy constructor to perform deep copy:
Program 2:
Output:
There are 2 other methods by which you can perform deep copy:
SerializationDemo.java:
Output:
And if you look at the file present in C:/temp/bytestream.txt, you can see
how the object is serialized into this file,
Question 57: What is SerialVersionUID?
Answer: SerialVersionUID: The serialization process at runtime associates an
id with each Serializable class which is known as SerialVersionUID. It is used
to verify the sender and receiver of the serialized object. The sender and
receiver must have the same SerialVersionUID, otherwise,
InvalidClassException will be thrown when you deserialize the object. A
Serializable class can declare its own UID explicitly by declaring a field. It
must be static, final and of type long. Remember, there is an exception for
SerialVersionUID that although it is static, it gets serialized too, so that at the
object deserialization the sender and receiver can be verified.
If a serializable class doesn’t explicitly declare a serialVersionUID, then the
serialization runtime will calculate a default one for that class based on
various aspects of class. This default serialVersionUID gets changed, when
you add a new field or remove the transient keyword from a variable or
convert the static variable to non-static variable. And if you are modifying
the class structure after Serialization has been done, you will not be able to
deserialize the object, see the example below:
Let’s change the Employee class in our previous example and remove the
transient keyword from salary variable:
Program 1:
We have already serialized the Employee object in our previous example,
now let’s try to de-serialize it back:
Output:
java.io.InvalidClassException: com.serialization.demo.Employee; local class
incompatible: stream classdesc serialVersionUID = -3697389390179909057,
local class serialVersionUID = -3759917827722067163
at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at
com.serialization.demo.DeserializationTest.main(DeserializationTest.java:13)
SerializationDemo.java:
Output:
Now, let’s add one more field ‘company’ and remove the transient keyword
from our Employee class. Here, as we are changing the class structure, let’s
see if we get the error of InvalidClassException again:
Program 3:
DeserializationTest.java:
Output:
Output:
Now, one thing to remember here is that the public no-arg constructor gets
called before readExternal() method, so we have to provide this no-arg
constructor or else we will get an exception during run-time.
Comment the public no-arg constructor from Employee.java:
Program 2:
So, if interviewer asks a question that you have a class which has 1000
variables and you want to serialize only 10 specific variables, your answer
should be using an Externalizable interface.
Some points to remember:
- Using Externalizable interface, we can implement custom logic
for serialization and deserialization of object
- When using Externalizable, we have to explicitly mention what
fields or variables we want to serialize
- When using Externalizable, a public no-arg constructor is
required
- Using Externalizable, we can also serialize transient and static
variables
- readExternal() method must read the values in the same
sequence and with the same types as were written by
writeExternal() method
ExternalizableDemo.java:
Output:
The capacity and age variable values are 0 because we did not serialize these
two variables.
ExternalizableDemo.java:
Output:
TestImmutable.java:
Here, after creating Employee object, the first change is done in local
address object and then we used the employee’s getter method to access
the address object and tried to change the value in it.
Output:
As, you can see that the value remained the same.
If we don’t follow the rule about mutable object reference present in the
class, let’s see what will happen in that case.
Let’s change the Employee class constructor and getter method:
Employee.java:
Now, if we run our TestImmutable.java class, below is the output:
Suppose, you have created a class Employee.java and compiled this class
and Emloyee.class file is created. Now, you want to use this class, the first
request to load this class will come to System/Application ClassLoader,
which will delegate the request to its parent, Extension ClassLoader which
further delegates to Primordial or Bootstrap class loader
Now, Bootstrap ClassLoader will look for this class in rt.jar, since this class is
not there, the request will come to Extension ClassLoader which looks in
jre/lib/ext directory and tries to locate this class there, if this class is found
there then Extension ClassLoader will load this class and Application
ClassLoader will not load this class, this has been done to maintain the
Uniqueness principle. But if the class is not loaded by Extension ClassLoader,
then this Employee.class will be loaded by Application ClassLoader from the
CLASSPATH.
Employee.java:
Output:
If you are thinking why null is printed when we tried to know which
classloader is loading the java.lang.System class then take a look at the
Javadoc :
We can also create our own custom class loader by extending the
ClassLoader class.
Question 65: What is Singleton Design Pattern and how it
can be implemented?
Answer: This is a famous interview question, as it involves many follow-up
questions as well. I will cover all of them here:
What is Singleton Design Pattern?
Singleton design pattern comes under Creational Design Patterns category
and this pattern ensures that only one instance of class exists in the JVM.
Singleton pattern is used in:
- logging, caching, thread pool etc.
- other design patterns like Builder, Prototype, Abstract Factory
etc.
- core java classes like java.lang.Runtime etc.
How to implement Singleton Pattern
To implement a Singleton pattern, we have different approaches but all of
them have the below common concepts:
Output:
We can also access the instance by using the classname like A.instance
because of static keyword but we will have to change its access modifier to
‘public’, so that it is visible outside the singleton class.
Let’s suppose you are creating a large object by using a lot of resources,
there may be a chance that object creation may throw an exception but the
above way of creating a singleton class does not provide any option for
exception handling as you can write try-catch only inside a block of code.
There is a solution to tackle this particular problem where you can create
the class instance inside a static block.
Lazy Initialization: using this way of creating Singleton class, the object will
not get created unless someone asks for it. Here we will create the class
instance inside the global access method.
This approach is suitable for only single-threaded application, suppose there
are 2 threads and both have checked that the instance is null and now they
are inside the “if(…)” condition, it will destroy our singleton pattern and both
threads will have different instances. So, we must overcome this problem so
that our singleton pattern doesn’t break in case of multi-threaded
environment.
Now, some people have faced issues with the above approach in java 1.4
and earlier versions, which was solved in later versions by using ‘volatile’
keyword with the above approach like below:
localRef variable is there for the cases where instance is already initialized
(discussed above), the volatile field is only accessed once because we have
written return localRef not return instance.
There is another approach where an inner static class is used to create the
Singleton class instance and it is returned from the global access method.
This approach is called Bill Pugh Singleton Implementation.
Bill Pugh Singleton Implementation Program:
The inner class does not get loaded at the time of class A loading, only when
someone calls getInstance() method, it gets loaded and creates the
Singleton instance.
Test.java:
Output:
As we can see from the output, the 2 instances have different hashcode,
thus destroying Singleton.
Now to prevent Singleton from Reflection, one simple solution is to throw
an exception from the private constructor, so when Reflection tries to
invoke private constructor, there will be an error.
TestSingletonEnum.java:
Output:
Output:
To prevent our Singleton class from Serialization, there is a method called
readResolve() which is called when ObjectInputStream has read an object
from the stream and is preparing to return it to the caller, so we can return
the only instance of this class from this method, and this way the only
instance of singleton will be assigned to instance2, see below:
A.java:
Test.java:
Output:
You can also throw an exception from the readResolve() method, but
returning the only instance approach is better as your program execution
will not stop.
One last way which can break Singleton property of a class is:
Cloning: As we know, Cloning is used to create duplicate objects (copy of the
original object). If we create a clone of the instance of our Singleton class
then a new instance will be created thus breaking our Singleton pattern.
See the program below:
TestSingleton.java:
Output:
As you can see, both instances have different hashcodes indicating our
Singleton pattern is broken, so to prevent this we can override clone method
in our Singleton class and either return the same instance or throw
CloneNotSupportedException from it.
See the program changes below:
Output:
clone() returning the same instance, see the program changes below:
Output:
Now, let’s suppose 2 threads are working on this class and both threads are
running on different processors having their own local copy of variable x. if
any thread modifies its value, the change will not be reflected back in the
original variable x in the main memory leading to data inconsistency because
the other thread is not aware of the modification.
So, to prevent data inconsistency, we can make variable x as volatile:
Now, all the threads will read and write the variable x from/to the main
memory. Using volatile, also prevents compiler from doing any reordering or
any optimization to the code.
Classes may get collected (unloaded) if the JVM finds they are no longer
needed and space may be needed for other classes. The permanent
generation is included in a full garbage collection. And Perm Gen was
available till Java 7, it is removed from Java 8 onwards and JVM uses native
memory for the representation of class metadata which is called MetaSpace.
There is a flag MaxMetaspaceSize, to limit the amount of memory used for
class metadata. If we do not specify the value for this, the Metaspace re-
sizes at runtime as per the demand of the running application.
Parallel/Throughput GC:
Parallel garbage collector uses multiple threads to perform the garbage
collection. By default, on a host with N CPUs, this collector uses N garbage
collector threads for collection. The number of collector threads can be
controlled with the command line option: -XX:ParallelGCThreads=<N>
It is called Throughput collector as it uses multiple CPUs to speed up the
application throughput. A drawback of this collector is that it pauses the
application threads while performing minor or full GC, so it is best suited for
applications where long pauses are acceptable. It is the default collector in
JDK 8.
It can be turned on by using below 2 options:
-XX:+UseParallelGC
With this command line option, you get a multi-thread young generation
collector with a single-threaded old generation collector. The option also
does single-threaded compaction of old generation.
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -
XX:+UseParallelGC -jar C:\temp\test.jar
-XX:+UseParallelOldGC
With this option, the GC is both a multithreaded young generation collector
and multithreaded old generation collector. It is also a multithreaded
compacting collector.
Compacting describes the act of moving objects in a way that there are no
holes between objects. After a garbage collection sweep, there may be holes
left between live objects. Compacting moves objects so that there are no
remaining holes. This compacting of memory makes it faster to allocate new
chunks of memory to the heap.
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -
XX:+UseParallelOldGC -jar C:\temp\test.jar
G1 Garbage Collector:
The Garbage First or G1 collector is a parallel, concurrent and incrementally
compacting low-pause garbage collector
G1 collector partitions the heap into a set of equal-sized heap regions. When
G1 performs garbage collection then a concurrent global marking phase is
performed to determine the liveliness of objects throughout the heap. After
this mark phase is complete, G1 knows which regions are mostly empty. It
collects unreachable objects from these regions first, which usually yields a
large amount of free space, also called Sweeping. So G1 collects these
regions (containing garbage) first, and hence the name Garbage-First.
It can be turned on by passing -XX:+UseG1GC in the command line options
java –Xmx25g –Xms5g -XX:+UseG1GC -jar C:\temp\test.jar
Java 8 has introduced one JVM parameter for reducing the unnecessary use
of memory by creating too many instances of the same String. This
optimizes the heap memory by removing duplicate String values to a global
single char[] array. We can use the -XX:+UseStringDeduplication JVM
argument to enable this optimization.
G1 is the default garbage collector in JDK 9.
-
When using Generics, there is no need of type-casting.
Before Generics:
After Generics:
-
By using generics, programmers can implement generic
algorithms that work on collections of different types, can be
customized and are type safe and easier to read.
Output:
Multi-threading: you will be asked many questions on multi-threading,
so, read as much as you can and whatever you can. Here, I am including
some of the important questions that are mostly asked in every interview.
Here a Task class extends Thread class and overrides the run() method which
contains the business logic, then we make an object of this Task and call the
start() method, which starts the thread execution. start() method internally
calls run() method.
Output:
If you see the outputs of this and previous program, you will see that they
are different, because any thread can get a chance to execute its run()
method, when the CPU resources are available.
if these methods were in Thread class, then thread T1 must know that
another thread T2 is waiting for this particular resource, so T2 can be
notified by something like T2.notify()
But in java, the object itself is shared among all the threads, so one thread
acquires the lock on this object’s monitor, runs the code and while releasing
the lock, it calls the notify or notifyAll method on the object itself, so that
any other thread which was waiting on the same object’s monitor will be
notified that now the shared resource is available. That is why these
methods are defined in the Object class.
Threads have no specific knowledge of each other. They can run
asynchronously and are independent. They do not need to know about the
status of other threads. They just need to call notify method on an object, so
whichever thread is waiting on that resource will be notified.
Let’s consider this with a real-life example:
Suppose there is a petrol pump and it has a single washroom, the key of
which is kept at the service desk. This washroom is a shared resource for all.
To use this shared resource, the user must acquire the key to the washroom
lock. So, the user goes to service desk, acquires the key, opens the door,
locks it from the inside and use the facility.
Meanwhile if another user arrives at the petrol pump and wants to use the
washroom, he goes to the washroom and found that it is locked. He goes to
the service desk and the key is not there because it is with the current user.
When the current user finishes, he unlocks the door and returns the key to
the service desk. He does not bother about the waiting users. The service
desk gives the key to waiting user. If there are more than one user waiting to
use the facility, then they must form a queue.
Now, apply this analogy to Java, one user is one thread and the washroom is
the shared resource which the threads wish to execute. The key will be
synchronized keyword provided by Java, through which thread acquires a
lock for the code it wants to execute and making other threads wait until the
current thread finishes. Java will not be as fair as the service station,
because any of the waiting threads may get a chance to acquire the lock,
regardless of the order in which the threads came. The only guarantee is
that all the waiting threads will get to use the shared resource sooner or
later.
In this example, the lock can be acquired on the key object or the service
desk and none of them is a thread. These are the objects that decide
whether the washroom is locked or not.
Output:
In the code, if you don’t write t2.join(), then current thread will not wait
from the t2 thread to die, see the output below when t2.join() statement is
commented from the code :
A Task class which implements Runnable and its run() method simply calls
the synchronized method of Hello class:
Our main class:
We have 2 objects of our Hello class, one object is shared among First and
Second thread, and one object is shared among Third and Fourth thread,
and we are starting these threads.
Output:
As you can see from the output, the First and Second thread are not having
any thread interference. Same way, Third and Fourth thread does not have
any thread interference but First and Third thread are entering the
synchronized method at the same time with their own object locks (Hello
obj1 and obj2).
Lock which is hold by First thread will only stop the Second thread from
entering the synchronized block, because they are working on the same
instance i.e. obj1, but it cannot stop Third or Fourth thread as they are
working on another instance i.e. obj2.
Output:
One thing to remember here is that Java synchronized keyword is re-entrant
in nature, it means if a synchronized method calls another synchronized
method which requires same lock then current thread which is holding the
lock can enter into that method without acquiring lock.
Output:
Let’s pass a negative number, so that exception will be thrown:
Output:
CachedThreadPoolExecutor:
This executor is mainly used when there are many short-lived tasks to be
executed. If you compare this with the fixed thread pool, here the number
of threads of this executor pool is not bounded. If all the threads are busy
executing the assigned tasks and if there is a new task, then a new thread
will be created and added to the pool. If a thread remains idle for close to
sixty seconds, it is terminated and removed from the cache.
Use this one, if you are sure that the tasks will be short-lived, otherwise
there will be a lot of threads in the pool which will lead to performance
issues.
How to create a CachedThreadPoolExecutor:
ExecutorService executor =
Executors.newCachedThreadPool();
ScheduledExecutor:
Use this executor, when you want to schedule your tasks, like run them at
regular intervals or run them after a given delay. There are 2 methods which
are used for scheduling tasks: scheduleAtFixedRate and
scheduleWithFixedDelay.
How to create ScheduledExecutor:
ExecutorService executor =
Executors.newScheduledThreadPool(4);
ScheduledExecutorService interface extends the ExecutorService interface.
Now, apart from using Executors class to create executors, you can use
ThreadPoolExecutor and ScheduledThreadPoolExecutor class also. Using
these classes, you can manually configure and fine-tune various parameters
of the executor according to your need. Let’s see at some of those
parameters:
BlockingQueue:
The queue to use for holding tasks before they are executed. This queue will
hold only the Runnable tasks submitted by the execute method, you can use
a ArrayBlockingQueue or LinkedBlockingQueue like:
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>
(100);
ThreadFactory:
The factory to use when the executor creates a new thread. Using thread
factories removes hardwiring of calls to new Thread, enabling applications to
use special thread subclasses, priorities, etc.
RejectedExecutionHandler:
This handler is used when a task is rejected by the executor because all the
threads are busy and the queue is full.
When this handler is not provided and the task submitted to execute()
method is rejected, then an unchecked RejectedExecutionException is
thrown.
But adding a handler is a good practice to follow, there is a method:
void rejectedExecution(Runnable r, ThreadPoolExecutor
executor);
This method will be invoked by ThreadPoolExecutor when execute() cannot
accept a task.