Are both the below approaches for lazy-initializing thread-safe singleton in java correct? Is there any performance difference? If not then why do we use the Holder pattern(Singleton2) instead of keeping it simple as in Singleton1 ?
Thanks in advance.
class Singleton1 {
private Singleton1() {
System.out.println("Singleton1-Constructor");
}
private static final Singleton1 inst1 = new Singleton1();
public static Singleton1 getInst1() {
return inst1;
}
}
class Singleton2 {
private Singleton2() {
System.out.println("Singleton2-Constructor");
}
public static class Holder {
private static final Singleton2 holderInst = new Singleton2();
}
public static Singleton2 getInst2() {
return Holder.holderInst;
}
}
public class App {
public static void main(String[] args) {
Singleton1.getInst1(); // without this statement the Singleton1 constructor doesnt get called.
Singleton2.getInst2(); // without this statement the Singleton2 constructor doesnt get called.
}
}
Singleton1 is not truly lazy, since if you add any other method to Singleton1 and call it from the main class, then the static inst1 will be initialized.
Try this:
public class Singleton1 {
private Singleton1() {
System.out.println("Singleton1-Constructor");
}
private static final Singleton1 inst1 = new Singleton1();
public static Singleton1 getInst1() {
return inst1;
}
public static void foo() {
}
}
public class Singleton2 {
private Singleton2() {
System.out.println("Singleton2-Constructor");
}
public static class Holder {
private static final Singleton2 holderInst = new Singleton2();
}
public static Singleton2 getInst2() {
return Singleton2.Holder.holderInst;
}
public static void bar() {
}
}
public class LazyInitializationApp {
public static void main(String[] args) {
Singleton1.foo();
Singleton2.bar();
}
}
Now running the app will print:
Singleton1-Constructor
But it will not print Singleton2-Constructor, because it is truly lazy.
Related
In my Android application I have to initialize a lot of static Objects before the first Activity starts. From what I know, static variables are initialized when classes are loaded. So, with time the amount of static objects in project began to grow and now I'm getting NullPointerExceptions. In my case static objects may call other static objects in their constructors. So my question is: could some static variables be initialized before variables they depend on and thus cause NullPointersExceptions? Is that possible?
Code example :
private static class HardwareManagersHolder implements HardwareManagers, IManagers {
private final AtomicBoolean senderAcquire = new AtomicBoolean(false);
private final AtomicInteger receiverAcquire = new AtomicInteger(0);
public IAudioManager audioManager;
public IVideoManager videoManager;
public IVibrationManager vibrationManager;
public IBatteryHelper batteryHelper;
#Override
public void configureManager() {
audioManager = AudioHelper.getInstance();
vibrationManager = VibrationManager.getInstance();
videoManager = VideoManager.getInstance();
batteryHelper = BatteryHelper.getInstance();
}
And an Object Holder:
public class VideoManager implements IVideoManager {
private static class VideoManagerHolder {
public static final VideoManager VIDEO_MANAGER_INSTANCE = new VideoManager();
}
public static VideoManager getInstance() {
return VideoManagerHolder.VIDEO_MANAGER_INSTANCE;
}
}
I tried to reconstruct your exception with the snippets you provided. I used the following code:
public interface IVideoManager {}
public class VideoManager implements IVideoManager {
private static class HardwareManagersHolder {
public IVideoManager videoManager;
public void configureManager() {
videoManager = VideoManager.getInstance();
}
}
private static class VideoManagerHolder {
public static final VideoManager VIDEO_MANAGER_INSTANCE = new VideoManager();
}
public static VideoManager getInstance() {
return VideoManagerHolder.VIDEO_MANAGER_INSTANCE;
}
public static void main(String[] arg) {
System.out.println("Start test");
HardwareManagersHolder h = new HardwareManagersHolder();
h.configureManager();
if (h.videoManager == null) {
System.out.println("VideoManager is null");
}
System.out.println("Test finished");
}
}
This code works on my machine. If this code is not working on yours, there is some other fault.
Are you initializing them in a static constructor? They would get called first for precisely this reason.
static
{
VIDEO_MANAGER_INSTANCE = new VideoManager();
}
I'm trying to write a junit test for one of my classes. The design was not done by me; this is a fairly old application, java7, struts1, and clydeDB framework.
The classes are set up like this:
ProcessObj,
IProcessObj (interface),
ProcessHome,
public class ProcessHome {
private static ProcessHome instance = new ProcessHome();
//default Constructor
private ProcessHome() {
}
public static ProcessHome getInstance() {
return instance;
}
public IProcessObj getProcessObj() throws POException {
return ProcessObj.getInstance(); //this is below
}
}
public class ProcessObj implements IProcessObj {
// instance
private static IProcessObj instance;
...
//constuctor
private ProcessObj() throws POException {
init();
}
static IProcessObj getInstance() throws POException {
if (instance == null) {
instance = new ProcessObj();
}
return instance;
}
//jUnit test setUp
#Before
public void setUp() throws Exception {
public static IProcessObj iPO;
iPAO = ProcessHome.getInstance()
.ProcessObj();
Constructor<ProcessObj> pa = ProcessObj.class
.getDeclaredConstructor();
pa.setAccessible(true);
iPO = pa.newInstance();`
...
It works fine up to here, but then in the ProcessObj, the initialization method goes through another set of classes that are set up exactly like the process objects that are above, for the data access layer.
Is there a way that I can create a usable instance of the process object? Can someone explain to me what exactly is going on here? I keep getting a InvocationTargetException.
Why you don't do something like this:
public class ProcessHome {
private static ProcessHome instance = new ProcessHome();
//default Constructor
private ProcessHome() {
}
public static ProcessHome getInstance() {
return instance;
}
public IProcessObj getProcessObj() throws POException {
return ProcessObj.getInstance(); //this is below
}
}
public class ProcessObj implements IProcessObj {
// instance
private static IProcessObj instance;
...
//constuctor
private ProcessObj() throws POException {
init();
}
static IProcessObj getInstance() throws POException {
if (instance == null) {
instance = new ProcessObj();
}
return instance;
}
//jUnit test class
public class ProcessHomeTest {
private IProcessObj iPO = ProcessHome.getInstance()
.ProcessObj();
#Test
public void testIProcessObj() throws Exception {
//use iPO heretest iPO
assertEquals("some","some");
}
I have two nested classes inside a class with the outer class extending another class. The structure is something like this.
public class EXTENSION_CLASS
{
public int Get_Value()
{
return(100);
}
}
public class OUTER extends EXTENSION_CLASS
{
public static class NESTED1
{
public void Method1()
{
int value=0;
value=Get_Value();
System.out.println("Method1: "+value);
}
}
public static class NESTED2
{
NESTED1 Nested1_Instance=new NESTED1();
public void Method2()
{
Nested1_Instance.Method1();
}
}
public void run()
{
NESTED2 Nested2_Instance=new NESTED2();
Nested2_Instance.Method2();
}
public static void main (String[] args)
{
OUTER New_Class=new OUTER();
New_Class.run();
}
}
I'm expecting the output: "Method1: 100". But, am getting the output: "OUTER.java:16: error: non-static method Get_Value() cannot be referenced from a static context value=Get_Value();". How can i make this working?
Cheers !
Rajesh.
One approach would be to have an instance of NESTED1 in NESTED2. For example:
private static class NESTED2
{
private NESTED1 nested1;
public NESTED2 (NESTED1 nested1) {
this.nested1 = nested1;
}
public void Method2()
{
nested1.Method1();
}
}
private static class NESTED2
{
public void Method2(NESTED1 nested1Instance)
{
nested1Instance.Method1();
}
}
That should do it with your class structure. Instead, with a modification like so....
private static class NESTED1
{
public *statc* void Method1()
{
...
}
}
private static class NESTED2
{
public *static* void Method2()
{
NESTED1.Method1();
}
}
... you could get away with no creation of objects.
If you make the methods static, you don't need to instantiate(create) a class object to call them first.
want to use non static method in static main, but i cant. I know this problem but, because i use INotificationObserver, i cant make registerObserver as static. So i could solve my problem.
How can i solve this problem ?? Thanks .
non-static variable this cannot be referenced from a static context
Test
public class PushTest implements INotificationObserver{
NotificationService ns = NotificationService.getInstance();
public static void main(String[] args) {
try {
ns.registerObserver(this); // How can i register ???
Interface
public interface INotificationSubject {
public void registerObserver(INotificationObserver o);
public void removeObserver(INotificationObserver o);
public void notifyObserver(PushedNotification notification);
}
*NotificationService *
public class NotificationService implements INotificationSubject{
protected static final Logger logger = Logger.getLogger(NotificationService.class);
private volatile static NotificationService uniqueFactory;
private ArrayList observers;
private NotificationService() {
observers = new ArrayList();
}
public static NotificationService getInstance() {
if (uniqueFactory == null) {
synchronized (NotificationService.class) {
if (uniqueFactory == null) {
uniqueFactory = new NotificationService();
}
}
}
return uniqueFactory;
}
public static INotification GetNotificationObject(DeviceTypes Types) {
INotification messageSender = null;
if (Types == Types.IOS) {
messageSender = new IosNotification();
}
return messageSender;
}
public void registerObserver(INotificationObserver o) {
observers.add(o);
}
public void removeObserver(INotificationObserver o) {
int i =
observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
public void notifyObserver(PushedNotification notification) {
for (int i = 0; i < observers.size(); i++) {
INotificationObserver observer = (INotificationObserver) observers.get(i);
observer.update(notification);
}
}
public void messageSendInfo(PushedNotification notification) {
notifyObserver(notification);
}
public void showSentInfo(PushedNotification notification) {
messageSendInfo(notification);
}
}
You need an instance:
INotificationObserver ino = new PushTest();
ns.registerObserver(ino);
Therefor, you don't need the ns attribute.
typical solution for this is initialize your class in the main method:
public class PushTest implements INotificationObserver{
NotificationService ns = NotificationService.getInstance();
public static void main(String[] args) {
PushTest pushTest = new Pushtest();
...
etc etc
I am trying to write a Singleton Lazy Loading Pattern. Here is the class:
public class IMDBLookup {
private static class LazyLoad {
private static final IMDBLookup IMDB_LOOKUP;
static {
IMDB_LOOKUP = new IMDBLookup();
}
}
public static IMDBLookup getInstance() {
return IMDBLookup.LazyLoad.IMDB_LOOKUP;
}
}
I am wondering whether or not I am doing it in a right way?
Thanks in advance.
I prefer to use enum for simplicity.
public enum IMDBLookup {
INSTANCE;
// add fields and methods here.
}
That is correct. You may want to simplify the inner (holder) class as private static final IMDBLookup IMDB_LOOKUP = new IMDBLookup(); for brevity (to get rid of the static initializer block.)
public class IMDBLookup {
private IMDBLookup(){
// without this I do not get why is it a singleton
// anyone could create instances of your class by the thousands
}
private static class LazyLoad {
private static final IMDBLookup IMDB_LOOKUP;
static {
IMDB_LOOKUP = new IMDBLookup();
}
}
public static IMDBLookup getInstance() {
return IMDBLookup.LazyLoad.IMDB_LOOKUP;
}
}
and you should probably use an enum (not completely sure I do this right)
public class IMDBLookup {
private IMDBLookup(){
}
private static enum LazyLoad {
IMDB_LOOKUP_INSTANCE;
private static final IMDB_LOOKUP = new IMDBLookup();
}
public static IMDBLookup getInstance() {
return LazyLoad.IMDB_LOOKUP_INSTANCE.IMDB_LOOKUP;
}
}
The advice you to think about clone & serialize
import java.io.Serializable;
public class DBConnectionInner implements Cloneable, Serializable {
private static final long serialVersionUID = 1173438078175185035L;
#Override
protected Object clone() throws CloneNotSupportedException {
return new CloneNotSupportedException("CLONE NOT SUPPORT FOR SINGTELTON");
}
protected Object readResolve() {
return getInstance();
}
private DBConnectionInner() {}
static DBConnectionInner getInstance() {
System.out.println("DBConnectionInner getInstance");
return LazyInit.instance;
}
public static class LazyInit {
private static final DBConnectionInner instance = new DBConnectionInner();
}
}