diff --git a/core-java-reflection/pom.xml b/core-java-reflection/pom.xml
new file mode 100644
index 0000000000..fc2e908fe8
--- /dev/null
+++ b/core-java-reflection/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+ core-java-reflection
+ 0.1.0-SNAPSHOT
+ core-java-reflection
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+
+
+
+
+ 3.10.0
+
+
\ No newline at end of file
diff --git a/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Action.java b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Action.java
new file mode 100644
index 0000000000..1459bf25c5
--- /dev/null
+++ b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Action.java
@@ -0,0 +1,5 @@
+package com.baeldung.reflection.voidtype;
+
+public interface Action {
+ void execute();
+}
diff --git a/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Calculator.java b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Calculator.java
new file mode 100644
index 0000000000..dcfbe72008
--- /dev/null
+++ b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Calculator.java
@@ -0,0 +1,21 @@
+package com.baeldung.reflection.voidtype;
+
+public class Calculator {
+ private int result = 0;
+
+ public int add(int number) {
+ return result += number;
+ }
+
+ public int sub(int number) {
+ return result -= number;
+ }
+
+ public void clear() {
+ result = 0;
+ }
+
+ public void print() {
+ System.out.println(result);
+ }
+}
diff --git a/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Defer.java b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Defer.java
new file mode 100644
index 0000000000..09817199fa
--- /dev/null
+++ b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Defer.java
@@ -0,0 +1,27 @@
+package com.baeldung.reflection.voidtype;
+
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public class Defer {
+ public static V defer(Callable callable) throws Exception {
+ return callable.call();
+ }
+
+ public static void defer(Runnable runnable) {
+ runnable.run();
+ }
+
+ public static R defer(Function function, T arg) {
+ return function.apply(arg);
+ }
+
+ public static void defer(Consumer consumer, T arg) {
+ consumer.accept(arg);
+ }
+
+ public static void defer(Action action) {
+ action.execute();
+ }
+}
diff --git a/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/MyOwnDefer.java b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/MyOwnDefer.java
new file mode 100644
index 0000000000..47468ee641
--- /dev/null
+++ b/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/MyOwnDefer.java
@@ -0,0 +1,15 @@
+package com.baeldung.reflection.voidtype;
+
+import java.util.concurrent.Callable;
+
+public class MyOwnDefer {
+ public static void defer(Runnable runnable) throws Exception {
+ Defer.defer(new Callable() {
+ @Override
+ public Void call() {
+ runnable.run();
+ return null;
+ }
+ });
+ }
+}
diff --git a/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/CalculatorUnitTest.java b/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/CalculatorUnitTest.java
new file mode 100644
index 0000000000..0ba22bf6e3
--- /dev/null
+++ b/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/CalculatorUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.reflection.voidtype;
+
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class CalculatorUnitTest {
+ @Test
+ void givenCalculator_whenGettingVoidMethodsByReflection_thenOnlyClearAndPrint() {
+ Method[] calculatorMethods = Calculator.class.getDeclaredMethods();
+ List calculatorVoidMethods = Arrays.stream(calculatorMethods)
+ .filter(method -> method.getReturnType().equals(Void.TYPE))
+ .collect(Collectors.toList());
+
+ assertThat(calculatorVoidMethods)
+ .allMatch(method -> Arrays.asList("clear", "print").contains(method.getName()));
+ }
+}
\ No newline at end of file
diff --git a/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/DeferUnitTest.java b/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/DeferUnitTest.java
new file mode 100644
index 0000000000..e2dc68effc
--- /dev/null
+++ b/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/DeferUnitTest.java
@@ -0,0 +1,81 @@
+package com.baeldung.reflection.voidtype;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+class DeferUnitTest {
+ @Test
+ void givenVoidCallable_whenDiffer_thenReturnNull() throws Exception {
+ Callable callable = new Callable() {
+ @Override
+ public Void call() {
+ System.out.println("Hello!");
+ return null;
+ }
+ };
+
+ assertThat(Defer.defer(callable)).isNull();
+ }
+
+ @Test
+ void givenVoidRunnable_whenDiffer_thenNoReturn() {
+ AtomicBoolean run = new AtomicBoolean(false);
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("Hello!");
+ run.set(true);
+ }
+ };
+
+ Defer.defer(runnable);
+
+ assertTrue(run.get());
+ }
+
+ @Test
+ void givenVoidFunction_whenDiffer_thenReturnNull() {
+ Function function = s -> {
+ System.out.println("Hello " + s + "!");
+ return null;
+ };
+
+ assertThat(Defer.defer(function, "World")).isNull();
+ }
+
+ @Test
+ void givenVoidConsumer_whenDiffer_thenReturnNull() {
+ AtomicBoolean run = new AtomicBoolean(false);
+
+ Consumer function = s -> {
+ System.out.println("Hello " + s + "!");
+ run.set(true);
+ };
+
+ Defer.defer(function, "World");
+
+ assertTrue(run.get());
+ }
+
+ @Test
+ void givenAction_whenDiffer_thenNoReturn() {
+ AtomicBoolean run = new AtomicBoolean(false);
+
+ Action action = () -> {
+ System.out.println("Hello!");
+ run.set(true);
+ };
+
+ Defer.defer(action);
+
+ assertTrue(run.get());
+ }
+}
\ No newline at end of file
diff --git a/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/MyOwnDeferUnitTest.java b/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/MyOwnDeferUnitTest.java
new file mode 100644
index 0000000000..e3c3612a22
--- /dev/null
+++ b/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/MyOwnDeferUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.reflection.voidtype;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class MyOwnDeferUnitTest {
+ @Test
+ void defer() throws Exception {
+ AtomicBoolean run = new AtomicBoolean(false);
+ Runnable runnable = () -> {
+ System.out.println("Hello!");
+ run.set(true);
+ };
+
+ MyOwnDefer.defer(runnable);
+
+ assertTrue(run.get());
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index b896514b3a..6cb0c6d570 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,6 +13,7 @@
lombok-custom
picocli
+ core-java-reflection