Skip to content

Commit 28bb7da

Browse files
committed
adding Reflection handling to other Singleton implementations
1 parent 314f273 commit 28bb7da

File tree

6 files changed

+38
-17
lines changed

6 files changed

+38
-17
lines changed

singleton/src/main/java/com/iluwatar/singleton/BillPughImplementation.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ public final class BillPughImplementation {
4040
* Private constructor to prevent instantiation from outside the class.
4141
*/
4242
private BillPughImplementation() {
43-
// private constructor
43+
// to prevent instantiating by Reflection call
44+
if (InstanceHolder.instance != null) {
45+
throw new IllegalStateException("Already initialized.");
46+
}
4447
}
4548

4649
/**

singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public final class InitializingOnDemandHolderIdiom {
4343
* Private constructor.
4444
*/
4545
private InitializingOnDemandHolderIdiom() {
46+
// to prevent instantiating by Reflection call
47+
if (HelperHolder.INSTANCE != null) {
48+
throw new IllegalStateException("Already initialized.");
49+
}
4650
}
4751

4852
/**

singleton/src/main/java/com/iluwatar/singleton/IvoryTower.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public final class IvoryTower {
3333
* Private constructor so nobody can instantiate the class.
3434
*/
3535
private IvoryTower() {
36+
// to prevent instantiating by Reflection call
37+
if (INSTANCE != null) {
38+
throw new IllegalStateException("Already initialized.");
39+
}
3640
}
3741

3842
/**

singleton/src/test/java/com/iluwatar/singleton/EnumIvoryTowerTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
*/
2525
package com.iluwatar.singleton;
2626

27+
import org.junit.jupiter.api.Test;
28+
29+
import static org.junit.jupiter.api.Assertions.assertThrows;
30+
2731
/**
2832
* EnumIvoryTowerTest
2933
*
@@ -37,4 +41,14 @@ public EnumIvoryTowerTest() {
3741
super(() -> EnumIvoryTower.INSTANCE);
3842
}
3943

44+
/**
45+
* Test creating new instance by reflection.
46+
*/
47+
@Override
48+
@Test
49+
void testCreatingNewInstanceByReflection() throws Exception {
50+
// Java does not allow Enum instantiation http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
51+
assertThrows(ReflectiveOperationException.class, EnumIvoryTower.class::getDeclaredConstructor);
52+
}
53+
4054
}

singleton/src/test/java/com/iluwatar/singleton/SingletonTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
import static java.time.Duration.ofMillis;
2828
import static org.junit.jupiter.api.Assertions.assertNotNull;
2929
import static org.junit.jupiter.api.Assertions.assertSame;
30+
import static org.junit.jupiter.api.Assertions.assertThrows;
3031
import static org.junit.jupiter.api.Assertions.assertTimeout;
3132

33+
import java.lang.reflect.InvocationTargetException;
3234
import java.util.ArrayList;
3335
import java.util.concurrent.Callable;
3436
import java.util.concurrent.Executors;
@@ -106,4 +108,14 @@ void testMultipleCallsReturnTheSameObjectInDifferentThreads() {
106108

107109
}
108110

111+
/**
112+
* Test creating new instance by reflection.
113+
*/
114+
@Test
115+
void testCreatingNewInstanceByReflection() throws Exception {
116+
var firstTimeInstantiated = this.singletonInstanceMethod.get();
117+
var constructor = firstTimeInstantiated.getClass().getDeclaredConstructor();
118+
constructor.setAccessible(true);
119+
assertThrows(InvocationTargetException.class, () -> constructor.newInstance((Object[]) null));
120+
}
109121
}

singleton/src/test/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLockingTest.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@
2424
*/
2525
package com.iluwatar.singleton;
2626

27-
import static org.junit.jupiter.api.Assertions.assertThrows;
28-
29-
import java.lang.reflect.InvocationTargetException;
30-
import org.junit.jupiter.api.Test;
31-
3227
/**
3328
* ThreadSafeDoubleCheckLockingTest
3429
*
@@ -42,15 +37,4 @@ public ThreadSafeDoubleCheckLockingTest() {
4237
super(ThreadSafeDoubleCheckLocking::getInstance);
4338
}
4439

45-
/**
46-
* Test creating new instance by reflection.
47-
*/
48-
@Test
49-
void testCreatingNewInstanceByReflection() throws Exception {
50-
ThreadSafeDoubleCheckLocking.getInstance();
51-
var constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor();
52-
constructor.setAccessible(true);
53-
assertThrows(InvocationTargetException.class, () -> constructor.newInstance((Object[]) null));
54-
}
55-
5640
}

0 commit comments

Comments
 (0)