Java Questions Answers
Java Questions Answers
Java Questions Answers
public - public means everyone can access it.That means it's in global
scope. As, main method is called by JVM [Java Virtual Machine],
which is actually out of the project scope, the access specifier of this
method is public. static - Java environment should be able to call this
method without creating an instance of the class , so this method must be
declared asstatic. void - the return type of this method is void means
there's no return value. main( ) - the name of the method, main because
it's the main method. String args[] - arguments to this method. This
method must be given an array of Strings, and the array will be called
'args'.
The program compiles properly but at run-time it will give "Main method
not public." message
Pass by reference means, passing the address itself rather than passing
the value. While, on the other hand, pass by value means passing a copy
of the value. Java, actually works as pass by value. Let’s check this with the
help of 2 examples. Examples: 1. By passing primitive data type: In
the below code, we have written a method called doInt(), which takes a int
value and decrease the value by one and printing it there. Now, from
main() method, we are passing the int i of value 10, then we are printing
from main(). public static void main(String[] args) { int i= 10;
System.out.print("OUTPUT: "); doInt(i); System.out.print(i); } public
static void doInt(int i) { i--; System.out.print(i+", "); } Output: And the
output of the above code is, 9 is printed from the doInt() method, whereas,
it is not reflected in main method, because, it is still printing 10. OUTPUT:
9, 10 Therefore, the conclusion over here is, it is passing the value, instead
of reference. 2. By Passing Object: Now, the second example, by passing
an object. Say, we have a class named, Employee, which has 2 fields
strName and intAge.
The purpose of garbage collection is to identify and discard objects that are
no longer needed by a program so that their resources can be reclaimed
and reused. A Java object is subject to garbage collection when it becomes
unreachable to the program in which it is used.
synchronized(this){ // do something }
The above code, will lock the object itself, when this piece of code has been
executed by a thread.
· the official core Java API, contained in the JDK or JRE, of one of the
editions of the Java Platform. The three editions of the Java Platform are
Java ME (Micro edition), Java SE (Standard edition), and Java EE
(Enterprise edition).
· unofficial APIs, developed by third parties, but not related to any JSRs.
1. If you want to extend the Thread class then it will make your class unable
to extend other classes as java is having single inheritance feature whereas
If you implement runnable interface, you can gain better object-oriented
design and consistency and also avoid the single inheritance problems.
2. Extending the thread will give you simple code structure in comparison
to Runnable Interface.
3. Using Runnable Interface, you can run class several times whereas
Thread have the start() method that can be called only once.
Vector :
1. It's synchronized.http://3.bp.blogspot.com/-
ig4JY8fk2Hc/UUdSPhrsxfI/AAAAAAAAAk8/1cnbnoePofs/s200/Java3.pn
g
1. It's unsynchronized.
Global variables are globally accessible. Java does not support globally
accessible variables due to following reasons:
public access
private access
The private (most restrictive) fields or methods cannot be used for classes
and Interfaces. It also cannot be used for fields and methods within an
interface. Fields, methods or constructors declared private are strictly
controlled, which means they cannot be accesses by anywhere outside the
enclosing class. A standard design strategy is to make all fields private and
provide public getter methods for them.
protected access
The protected fields or methods cannot be used for classes and Interfaces.
It also cannot be used for fields and methods within an interface. Fields,
methods and constructors declared protected in a superclass can be
accessed only by subclasses in other packages. Classes in the same package
can also access protected fields, methods and constructors as well, even if
they are not a subclass of the protected member’s class.
default access
Static means one per class, not one for each object no matter how many
instance of a class might exist. This means that you can use them without
creating an instance of a class.Static methods are implicitly final, because
overriding is done based on the type of the object, and static methods are
attached to a class, not an object. A static method in a superclass can be
shadowed by another static method in a subclass, as long as the original
method was not declared final. However, you can't override a static method
with a nonstatic method. In other words, you can't change a static method
into an instance method in a subclass.
A final class can't be extended ie., final class may not be subclassed.
Example
Yes it is possible. While starting the application we mention the class name
to be run. The JVM will look for the Main method only in the class whose
name you have mentioned. Hence there is not conflict amongst the
multiple classes having main method.
No the program fails to compile. The compiler says that the main method is
already defined in the class.
Class SampleClass :
Example:
Class SampleClass :
objSampleClass.setStrName("Ashoka Maurya");
objSampleClass.setStrAddress("Magadha");
objSampleClass.setStrUsername("Chakravartin");
objSampleClass.setStrPassword("Ashokavadana");
Class DeserializeFileToObject :
Output :
Here, we can see, we get all the data from the deserialized object except
strPassword, as it is decleared astransient.
Primitive type
Wrapper class
boolean
Java.lang.Boolean
byte
Java.lang.Byte
char
Java.lang.Char
double
Java.lang.Double
float
Java.lang.Float
6
int
Java.lang.Int
long
Java.lang.Long
short
Java.lang.Short
Unckecked Exception:
An applet is a container.
Exception class:
It's also the class that you will sub-class to create your own custom
exception types.
Error class:
String class :
StringBuffer class :
It can be divided into 2 types. They are - static nested class & non-static nested class
Static Nested Class:
Nested class which is declared static is static nested class.
Its methods & variables are associated with is mother/outer class.
It can be used only through object reference.
It is accessed using enclosing class name.
Example:MotherClass.StaticNestedClass
It interacts with enclosing class or other class like any other top-level class.
It is use for reading stream of data from a file in the form of raw bytes(8-bit).
Very useful to read image.
It can also read character files.
Hierarchy of Class FileInputStream:
Class FileReader:
Hierarchy of Class FileReader:
Error is unpredictable. It can occur at any point and recover is also quite impossible. So it is meaningless to
Code:
package com.interview.question.java;
public class PaserStringToDouble {
/**
*
* Sample class that shows how to parse a String to double.
*
* @author http://interviewquestionjava.blogspot.com
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// set a decimal value in a string with
// white space on both end.
String strValue = " 12.329 ";
}
Output:
dblValue: 12.329
dblValue2: 12.329
dblValue3: 12.329
dblValue4: 12.329
abstract:
This is used to define a class or a method as an abstract operation. When a method is
declared as abstract, that means, the method where it is declared (within the class) have
no body of the method rather the method can be overridden, through inheritance and
define it's body.
When a class contains any abstract method, it must be declared as abstract.
An abstract class cannot be final.
An abstract method cannot be final, static nor native.
Code:
package com.interview.question.java;
abstract class SampleAbstractClass {
/**
*
* Sample abstract class.
*
* @author http://interviewquestionjava.blogspot.com
*
*/
// Sample abstract method.
public abstract void sampleabstractmethod() ;
public void sampleNormalMethod(){
System.out.println("SampleAbstractClass.sampleNormalMethod()");
}
}
public class TestAbstractClass{
/**
*
* Sample class to call SampleAbstractClass.
*
* @author http://interviewquestionjava.blogspot.com
*
*/
public static void main(String[] args) {
SampleAbstractClass objSampleAbstractClass
= newSampleAbstractClass() {
@Override
public void sampleabstractmethod() {
System.out
.println("TestAbstractClass.main(...).new SampleAbstractClass()
{...}.sampleabstractmethod()");
}
};
objSampleAbstractClass.sampleabstractmethod();
}
}
Output:
Overloading:
Java identifies method by its name and signature. So, if the combination of method name and signature is
unique, the compiler doesn’t have any issue to identify it. When you use overloaded methods,
the java compile will automatically identifies the right version of the method by number and/or types
of passing parameters. But you can’t declare more than one method with same name and passing
parameters. The compiler doesn’t consider return types when validating uniqueness of a method. That
means you can’t have two methods with same name and passing parameters with different return type.
Code:
package com.interview.question.java;
public class OverloadingDemo {
/**
*
*
* @author http://interviewquestionjava.blogspot.com
*
**/
private int a;
public OverloadingDemo(){
}
public OverloadingDemo(int a){
this.a = a;
}
public int add(int num){
a +=num;
return a;
}
public int add(String str){
a+= Integer.valueOf(str);
return a;
}
public int add(int num1, int num2){
a += num1;
a += num2;
return a;
}
public static void main(String[] args) {
System.out.println(objOverloadingDemo1.add(5));
System.out.println(objOverloadingDemo1.add("3"));
System.out.println("-----");
System.out.println(objOverloadingDemo2.add(5));
System.out.println(objOverloadingDemo2.add("3"));
}
Output:
5
16
-----
10
13
21
Overriding is the technique of inheriting a class and redefining the behaviors of the super class. That
means, when you define a method in subclass with the same signature (name, plus the number and the type
of its parameters) and return type as in the superclass, then you are overriding the method of the superclass
in your subclass, and the technique is known as method overriding.
In method overriding, method name, method input parameters and return types in subclass should
be same in superclass. It can only modify the behaviors. It can return a subtype of the original return
type defined in superclass, and this technique is known as covariant return type [Java 1.5 or above
support this]. For example, suppose the return type in superclass is java.util.Map, you can change it
to java.util.HashMap in subclass, as HashMap is a subtype of Map.
You can also use @Override annotation [which is available in Java 1.5 or above] to tell
the compiler that you are trying to override a method in the superclass. And, fof any reason, if the compile
is unable to detect that method, it will generate an error.
In method overriding in java, you can level up the access level but you can’t level it down. That
means, if amethod is declared as protected in superclass, it can be set as public is subclass but not
as private.
Code:
Super Class :
package com.interview.question.java;
import java.util.HashMap;
import java.util.Map;
public class SuperClass {
/**
*
*
* @author http://interviewquestionjava.blogspot.com
*
**/
/* the return type of this method is Map and in subclass it will
be changed to HashMap */
public Map methodForcovariant(){
Map map = new HashMap();
return map;
}
System.out.println("SuperClass.sampleMethod()");
}
protected void protectedMethod(){
System.out.println("SuperClass.protectedMethod()");
}
public final void finalMethod(){
System.out.println("SuperClass.finalMethod()");
}
Sub Class:
package com.interview.question.java;
import java.util.HashMap;
import java.util.Map;
public class OverridingDemo extends SuperClass{
/**
*
*
*
@Override
public HashMap methodForcovariant(){
HashMap hmp = new HashMap();
return hmp;
}
/* Overriding:
@Override
public void sampleMethod(){
@Override
public void protectedMethod(){
System.out.println("OverridingDemo.protectedMethod()");
}
public static void main(String[] args) {
objSuperClass.sampleMethod();
objOverridingDemo.sampleMethod();
}
Output:
SuperClass.sampleMethod()
OverridingDemo.sampleMethod()
methodForcovariant() – it shows the change of return type to its subtype during method overriding.
short
long
float
double
boolean
char
String
Singleton in one of the most popular yet controversial design pattern, in the world of object oriented
programming. It's one of those patterns, that every developer comes to know first and again it's one of of
those patterns, that even experience developers get confused with it's proper implementation style. So,
over here, we will first take a deeper look on the concept of Singleton design pattern and then we will
discuss all the popular implementation styles of Singleton in java with suitable examples.
This post is a little bit bigger than usual. So please be patient, because it's worth reading.
Concept
Singleton is a software design pattern to limit the instantiation of a class to one, which will be globally
accessible. That means it’s a technique by which a class only have one instance/object and this object
can be accessed globally. It is a part of Gang of Four design pattern and it comes under creational
design patterns.
Applications, often needs to create single instance of a class, and that instance will be used throughout
the application. Examples like logging, database access, etc. We could pass such an instance from method
to method, or we can also assign it to each object in the application. But, that will create lots of
complexity. On the other hand, we could use a single instance to communicate with a class. Hence, the
class could create and manage a single instance of its own. And when needed, just talk to that class.
Principles of Singleton
Therefore, the principles of Singleton design pattern are -
1. The implementing class should have only one instance.
2. Access point of this single instance should be global.
2. The constructor should be private, so that, no one from outside can initialize this class.
3. A public static method which will expose the private member of the class to the outer world.
Well, there are some advantages of using Singleton over static class.
1. Static class can only have static members, where in Singleton pattern implemented class can
have non-static members.
2. A Singleton class can implement interfaces as well as extend classes but a static class
can extend classes, without inheriting their instance members.
3. A static class can’t be a top level class. It should be always nested class. That means, under some non-
static class. Because, by definition static means that it belongs to a class it is in.
4. We can clone an object of a Singleton class, but in static class, that is not possible.
5. Again, Singleton supports the features like polymorphism while, for a static class it’s not possible.
6. Singleton classes can also supports the lazy loading facility, which is not supported in a static class.
Implementation Styles
In Java programming language, Singleton pattern can be archive by different implementation style.
Each has some pros and corns. One single style is not suitable for every situation. So I think you should
know, all of them, and use it as per your requirement.
Now, we are going to discuss about some of the most popular implementation style.
Simple Lazy Initialization is the most basic style for lazy loading. It's good for the newbies to
understand the concept and structure of Singleton pattern.The concept of this style is to declare the
private static instance of the class by setting the initial value as null during class load, keeping the actual
initialization for the first call. That means, the actual initialization of the single instance of the class is
only happening when for the first time the class has been called.
Let’s take a look on the below example. The class LazyInitializationThreadUnsafe is a singleton class,
which contains a counter, every time called gives you a sequential incremental number.
Example: Class LazyInitializationThreadUnsafe
package interview.question.java.singleton;
/**
*
* single thread application. This class also provides a public method named
* counter() which will always returns integer type sequenced counter value
*
*
**/
public class LazyInitializationThreadUnsafe {
/*
* The integer type counter will hold the value of the counter. The scope of
* this field is private, so its only accessible via the counter method.
* It's static so that only one copy of this variable will be available
*/
*/
private static LazyInitializationThreadUnsafe instance = null;
/*
*/
private LazyInitializationThreadUnsafe() {
System.out
.println("LazyInitializationThreadUnsafe.LazyInitializationThreadUnsafe()");
}
/*
* The method getInstance() will return the only instance of the class
*/
if (instance == null) {
instance = new LazyInitializationThreadUnsafe();
}
return instance;
}
/*
* This sample method will increase the counter by 1 and returns its value.
*/
public int counter() {
counter++;
System.out.println("LazyInitializationThreadUnsafe.counter()");
return counter;
}
private static LazyInitializationThreadUnsafe instance = null;
if (instance == null) {
instance = new LazyInitializationThreadUnsafe();
}
So, it will be initialize only for the first time the getInstance() method has been called.
But, this style is not thread safe. Its only good for single threaded environment.
Life cycle:
• Initializes during first use.
Pros:
• It supports lazy initialization, so it will only been loaded to the memory when it’s actually needed for
the first time.
Corns:
• It’s preferable only on single thread environment.
Let’s take a look on an example. The below class LazyInitializationThreadSafe is a thread safe lazy
initialization style.
Example: Class LazyInitializationThreadSafe
package interview.question.java.singleton;
/**
*
* multithreaded application.
*
**/
public class LazyInitializationThreadSafe {
/*
*/
/*
*
*/
private static LazyInitializationThreadSafe instance = null;
/*
* The constructor of the LazyInitializationThreadSafe class is in
*/
private LazyInitializationThreadSafe() {
System.out
.println("LazyInitializationThreadSafe.LazyInitializationThreadSafe()");
}
/*
* The static method getInstance() will return the only instance
*/
if (instance == null) {
instance = new LazyInitializationThreadSafe();
}
return instance;
}
/*
*/
public int counter() {
counter++;
System.out.println("LazyInitializationThreadSafe.counter()");
return counter;
}
Now, in this class you will find only one difference from the previous example (Class
LazyInitializationThreadUnsafe), that is, I use the synchronized Now, in this class getInstance() method.
That means, concurrent threads will use this method in atomic way. Thus, it’s safe from concurrent usage
of this method by multiple threads. And it becomes thread safe.
Life cycle:
• Initializes during first use.
• Destroyed at application shutdown.
Pros:
• Thread safe
• It uses lazy loading so it’s been initialized during its actual usage.
Corns:
• A bit slower that not thread safe style, the getInstance() goes through synchronized method. So it’s
locking the resource every time you call it.
Double Check Locking:
Another technique to implement thread safe lazy initialization is double check locking. This concept
will work fine in Java 5 or above. This concept is introduced to optimize the thread safe lazy
initialization styleof the Singleton pattern, which locks the resources, every time you try to get the
instance of the class using a public scoped method.
package interview.question.java.singleton;
/**
*
* check lock style. This class also provides a public method named counter()
*
*
**/
public class DoubleCheckLock {
/*
* The static private member instance of type DoubleCheckLock Class will
*/
/*
* The integer type counter will hold the value of the counter. The scope of
* this field is private, so its only accessible via the counter method.
* It's static so that only one copy of this variable will be available
*/
/*
*/
private DoubleCheckLock() {
System.out.println("DoubleCheckLock.DoubleCheckLock()");
}
/*
* The method getInstance() will return the only instance of the class
*/
if (instance == null) {
synchronized (DoubleCheckLock.class) {
if (instance == null) {
instance = new DoubleCheckLock();
}
}
}
return instance;
}
/*
* This sample method will increase the counter by 1 and returns its value.
*/
public int counter() {
counter++;
System.out.println("DoubleCheckLock.counter()");
returncounter;
}
Now, over here if you see, you will find the difference is in technique of initializing the instance
insidegetInstance() method.
if (instance == null) {
synchronized (DoubleCheckLock.class) {
if (instance == null) {
instance = new DoubleCheckLock();
}
}
}
You can also see that, we use the volatile keyword, when declaring the instance of the class. That’s, to
inform the JVM that writes to the field should always be synchronously flushed to memory, and that reads
of the field should always read from memory.
Life cycle:
• Initializes during first use.
Pros:
• Thread safe style.
• Performance wise it’s faster than Thread safe lazy initialization as its only locking during initialization.
Corns:
• Code complexity.
• Should only use in java 5 or above.
package interview.question.java.singleton;
/**
*
* threaded or multithreaded application.
*
*
**/
public class EagerInitialization {
/*
*/
/*
*
*/
/*
*/
private EagerInitialization() {
System.out.println("EagerInitialization.EagerInitialization()");
}
/*
* The static method getInstance() will return the only instance
return INSTANCE;
}
/*
*/
public int counter() {
counter++;
System.out.println("EagerInitialization.counter()");
return counter;
}
In this example, you can see its simply initializing the instance during declaration under private static
final clause. And returns it via a public static method getInstance().
Life cycle:
• Initializes during class load.
• Destroyed at application shutdown.
Pros:
• Thread safe.
• Performance wise, faster than lazy initialization, as it’s not locking any resource by synchronized.
• The instance is final, so scope of redefining, thus, no scope of multiple instance.
Corns:
• Initializes during class load, so it is occupying memory, even when it’s not required.
package interview.question.java.singleton;
/**
*
* Static Block Initialization style. This class also provides a public method
* named counter() which will always returns integer type sequenced counter
* value
*
*
**/
public class StaticBlockInitialization {
/*
* The integer type counter will hold the value of the counter. The scope of
* this field is private, so its only accessible via the counter method.
* It's static so that only one copy of this variable will be available
*/
/*
*/
/*
*/
static {
try {
INSTANCE = new StaticBlockInitialization();
counter = 0;
} catch (Exception e) {
}
}
/*
* The constructor of the StaticBlockInitialization class is in private
*/
private StaticBlockInitialization() {
System.out
.println("StaticBlockInitialization.StaticBlockInitialization()");
}
/*
* The static method getInstance() will return the only instance of the
* classStaticBlockInitialization.
*/
return INSTANCE;
}
/*
* This sample method will increase the counter by 1 and returns its value.
*/
public int counter() {
counter++;
System.out.println("StaticBlockInitialization.counter()");
return counter;
}
}
Here, you can see we are initializing the instance of the class under a static block. And we are also doing
it under try catch block, to provide an error check during initialization.
Life cycle:
• Initializes during class load.
• Destroyed at application shutdown.
Pros:
• Thread safe.
• Performance wise, faster than lazy initialization, as it’s not locking any resource by synchronized.
• The instance is final, so scope of redefining, thus, no scope of multiple instance.
• Initializing under try catch block for error check.
Corns:
• Initializes during class load, so it is occupying memory, even when it’s not required.
package interview.question.java.singleton;
/**
*
* The class DemandHolderIdiom is Singleton Class which implements the Demand
*
*
**/
public class DemandHolderIdiom {
/*
* The integer type counter will hold the value of the counter. The scope of
* this field is private, so its only accessible via the counter method.
* It's static so that only one copy of this variable will be available
*/
/*
*/
private DemandHolderIdiom() {
System.out.println("DemandHolderIdiom.DemandHolderIdiom()");
}
/*
*/
/*
*/
}
/*
* The static method getInstance() will return the only instance of the
* class.
*/
returnSingletonInstanceHolder.INSTANCE;
}
/*
* This sample method will increase the counter by 1 and returns its value.
*/
publicint counter() {
counter++;
System.out.println("DemandHolderIdiom.counter()");
returncounter;
}
Over here, you can see, the instance of the singleton class has been declared and initialized under a
static inner class SingletonInstanceHolder. And when getInstance() is called, it’s the return the instance
under the inner class.
Now, the question is, how is Domain Holder Idiom working as lazy initialization style?
The answer is, when the class DemandHolderIdiom is loaded, it goes through initialization of only the
static fields. Since it doesn’t have any static variable to initialize, SingletonInstanceHolder is not
loaded during class loading. So, when it will initialize? Well, it will only loaded when the JVM thinks that
SingletonInstanceHolder must be executed. And that is only when this inner class has been called from
the getInstance() method for the first time. Now, when this inner class is loaded, all its static variables
are also loaded. So the instance is also initialized by executing the private constructor of the outer class.
You can also read Java Language Specification (JLS) for more details about class loading and
initialization. As the class initialization phase is guaranteed by the JLS to be serial, i.e., non-concurrent,
so no further synchronization is required in the static getInstance() method during loading and
initialization.
Life cycle:
• Initializes during first use.
• Lazy loading.
• No need of resource locking to make it thread safe. Thus, performance is also good.
Corns:
• No such disadvantage as far. Still, it should be used when you need the lazy loading facility. Else, early
loading is simple to understand and use.
package interview.question.java.singleton;
/**
*
* public method named counter() which will always returns integer type
*
*
**/
public enum UsingEnum {
Instance;
/*
* The integer type counter will hold the value of the counter. The scope of
* this field is private, so its only accessible via the counter method.
* It's static so that only one copy of this variable will be available
*/
/*
* This sample method will increase the counter by 1 and returns its value.
*/
public int counter() {
counter++;
System.out.println("UsingEnum.counter()");
return counter;
}
public enum UsingEnum {
Instance;
}
By this only your singleton is created. So, don’t even need any locking for thread safety. Enum also
supports serialization. But it is unable to extend any class [read more for details].
Life cycle:
• Initializes during first use.
• Destroyed at application shutdown.
Pros:
• Thread safe.
• Supports serialization.
• No locking is needed, so performance is better.
• Code simplicity.
Corns:
• Available from java 5
• Unable to extend any class.
Now, it’s time to test the all above singleton classes. For that, we have a Test class, which simple calls all
the above classes twice, to see if its initializing once or more, by using a loop.
package interview.question.java.singleton;
/**
*
* The class Test will call all the singleton classes to test.
*
*
**/
public class Test {
public static void main(String[] args) {
//LasyInitializationThreadUnsafe
LasyInitializationThreadUnsafelasyInitializationSingleThread =
LasyInitializationThreadUnsafe
.getInstance();
System.out.println(lasyInitializationSingleThread.counter());
//LasyInitializationThreadSafe
LasyInitializationThreadSafelasyInitializationThreadSafe =
LasyInitializationThreadSafe
.getInstance();
System.out.println(lasyInitializationThreadSafe.counter());
//DoubleCheckLock
System.out.println(doubleCheckLock.counter());
//EagerInitialization
.getInstance();
System.out.println(eagerInitialization.counter());
//StaticBlockInitialization
StaticBlockInitializationstaticBlockInitialization =
StaticBlockInitialization
.getInstance();
System.out.println(staticBlockInitialization.counter());
//DemandHolderIdiom
.getInstance();
System.out.println(demandHolderIdiom.counter());
//UsingEnum
System.out.println(UsingEnum.Instance.counter());
System.out.println("\n\n");
}
}
}
Output:
Now, from the output it’s clear that, all the singleton classes have been initialized for one time.
LasyInitializationThreadUnsafe.LasyInitializationThreadUnsafe()
LasyInitializationThreadUnsafe.counter()
LasyInitializationThreadSafe.LasyInitializationThreadSafe()
LasyInitializationThreadSafe.counter()
DoubleCheckLock.DoubleCheckLock()
DoubleCheckLock.counter()
EagerInitialization.EagerInitialization()
EagerInitialization.counter()
StaticBlockInitialization.StaticBlockInitialization()
StaticBlockInitialization.counter()
DemandHolderIdiom.DemandHolderIdiom()
DemandHolderIdiom.counter()
UsingEnum.counter()
1
LasyInitializationThreadUnsafe.counter()
LasyInitializationThreadSafe.counter()
DoubleCheckLock.counter()
EagerInitialization.counter()
StaticBlockInitialization.counter()
DemandHolderIdiom.counter()
UsingEnum.counter()
Conclusion
Well, after discussing all the implementation styles, we may think the Enum Singleton Style and Domain
Holder Idiom are the most smarter ways to implement Singleton pattern in java. But that doesn't mean
other styles are irrelevant. Styles like Simple Lazy Initialization Style and Early Initialization are very
good for learning phase. Because you can get the concept and structure of a singleton class very clearly
form these patterns. And remember java.lang.Runtime uses Early Initialization too.
Therefore, when it comes to Singleton Implementation style, choose wisely and code smartly.