This commit is contained in:
Jonathan Cook
2019-10-23 15:01:44 +02:00
parent db85c8f275
commit 684ec0d2e3
20486 changed files with 1642483 additions and 0 deletions
@@ -0,0 +1,9 @@
## Relevant Articles
- [Void Type in Java](https://www.baeldung.com/java-void-type)
- [Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields)
- [Method Parameter Reflection in Java](http://www.baeldung.com/java-parameter-reflection)
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
- [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection)
- [Changing Annotation Parameters At Runtime](http://www.baeldung.com/java-reflection-change-annotation-params)
- [Dynamic Proxies in Java](http://www.baeldung.com/java-dynamic-proxies)
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-reflection</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-reflection</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-java</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
</dependency>
</dependencies>
<build>
<finalName>core-java-reflection</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<assertj-core.version>3.10.0</assertj-core.version>
</properties>
</project>
@@ -0,0 +1,19 @@
package com.baeldung.dynamicproxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicInvocationHandler implements InvocationHandler {
private static Logger LOGGER = LoggerFactory.getLogger(DynamicInvocationHandler.class);
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
LOGGER.info("Invoked method: {}", method.getName());
return 42;
}
}
@@ -0,0 +1,36 @@
package com.baeldung.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TimingDynamicInvocationHandler implements InvocationHandler {
private static Logger LOGGER = LoggerFactory.getLogger(TimingDynamicInvocationHandler.class);
private final Map<String, Method> methods = new HashMap<>();
private Object target;
TimingDynamicInvocationHandler(Object target) {
this.target = target;
for(Method method: target.getClass().getDeclaredMethods()) {
this.methods.put(method.getName(), method);
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.nanoTime();
Object result = methods.get(method.getName()).invoke(target, args);
long elapsed = System.nanoTime() - start;
LOGGER.info("Executing {} finished in {} ns", method.getName(), elapsed);
return result;
}
}
@@ -0,0 +1,18 @@
package com.baeldung.reflect;
public class Person {
private String fullName;
public Person(String fullName) {
this.fullName = fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getFullName() {
return fullName;
}
}
@@ -0,0 +1,39 @@
package com.baeldung.reflection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class BaeldungReflectionUtils {
private static final Logger LOG = LoggerFactory.getLogger(BaeldungReflectionUtils.class);
static List<String> getNullPropertiesList(Customer customer) throws Exception {
PropertyDescriptor[] propDescArr = Introspector.getBeanInfo(Customer.class, Object.class).getPropertyDescriptors();
return Arrays.stream(propDescArr)
.filter(nulls(customer))
.map(PropertyDescriptor::getName)
.collect(Collectors.toList());
}
private static Predicate<PropertyDescriptor> nulls(Customer customer) {
return pd -> {
boolean result = false;
try {
Method getterMethod = pd.getReadMethod();
result = (getterMethod != null && getterMethod.invoke(customer) == null);
} catch (Exception e) {
LOG.error("error invoking getter method");
}
return result;
};
}
}
@@ -0,0 +1,56 @@
package com.baeldung.reflection;
public class Customer {
private Integer id;
private String name;
private String emailId;
private Long phoneNumber;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", emailId=" + emailId + ", phoneNumber=" +
phoneNumber + "]";
}
Customer(Integer id, String name, String emailId, Long phoneNumber) {
super();
this.id = id;
this.name = name;
this.emailId = emailId;
this.phoneNumber = phoneNumber;
}
public Long getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(Long phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
@@ -0,0 +1,7 @@
package com.baeldung.reflection;
public class Employee extends Person {
public int employeeId;
}
@@ -0,0 +1,7 @@
package com.baeldung.reflection;
public class MonthEmployee extends Employee {
protected double reward;
}
@@ -0,0 +1,8 @@
package com.baeldung.reflection;
public class Person {
protected String lastName;
private String firstName;
}
@@ -0,0 +1,23 @@
package com.baeldung.java.reflection;
public abstract class Animal implements Eating {
public static final String CATEGORY = "domestic";
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected abstract String getSound();
}
@@ -0,0 +1,36 @@
package com.baeldung.java.reflection;
public class Bird extends Animal {
private boolean walks;
public Bird() {
super("bird");
}
public Bird(String name, boolean walks) {
super(name);
setWalks(walks);
}
public Bird(String name) {
super(name);
}
@Override
public String eats() {
return "grains";
}
@Override
protected String getSound() {
return "chaps";
}
public boolean walks() {
return walks;
}
public void setWalks(boolean walks) {
this.walks = walks;
}
}
@@ -0,0 +1,23 @@
package com.baeldung.java.reflection;
import java.lang.annotation.Annotation;
public class DynamicGreeter implements Greeter {
private String greet;
public DynamicGreeter(String greet) {
this.greet = greet;
}
@Override
public Class<? extends Annotation> annotationType() {
return DynamicGreeter.class;
}
@Override
public String greet() {
return greet;
}
}
@@ -0,0 +1,5 @@
package com.baeldung.java.reflection;
public interface Eating {
String eats();
}
@@ -0,0 +1,24 @@
package com.baeldung.java.reflection;
public class Goat extends Animal implements Locomotion {
public Goat(String name) {
super(name);
}
@Override
protected String getSound() {
return "bleat";
}
@Override
public String getLocomotion() {
return "walks";
}
@Override
public String eats() {
return "grass";
}
}
@@ -0,0 +1,10 @@
package com.baeldung.java.reflection;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Greeter {
public String greet() default "";
}
@@ -0,0 +1,58 @@
package com.baeldung.java.reflection;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
public class GreetingAnnotation {
private static final String ANNOTATION_METHOD = "annotationData";
private static final String ANNOTATION_FIELDS = "declaredAnnotations";
private static final String ANNOTATIONS = "annotations";
public static void main(String ...args) {
Greeter greetings = Greetings.class.getAnnotation(Greeter.class);
System.err.println("Hello there, " + greetings.greet() + " !!");
Greeter targetValue = new DynamicGreeter("Good evening");
//alterAnnotationValueJDK8(Greetings.class, Greeter.class, targetValue);
alterAnnotationValueJDK7(Greetings.class, Greeter.class, targetValue);
greetings = Greetings.class.getAnnotation(Greeter.class);
System.err.println("Hello there, " + greetings.greet() + " !!");
}
@SuppressWarnings("unchecked")
public static void alterAnnotationValueJDK8(Class<?> targetClass, Class<? extends Annotation> targetAnnotation, Annotation targetValue) {
try {
Method method = Class.class.getDeclaredMethod(ANNOTATION_METHOD, null);
method.setAccessible(true);
Object annotationData = method.invoke(targetClass);
Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);
Map<Class<? extends Annotation>, Annotation> map = (Map<Class<? extends Annotation>, Annotation>) annotations.get(annotationData);
map.put(targetAnnotation, targetValue);
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public static void alterAnnotationValueJDK7(Class<?> targetClass, Class<? extends Annotation> targetAnnotation, Annotation targetValue) {
try {
Field annotations = Class.class.getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);
Map<Class<? extends Annotation>, Annotation> map = (Map<Class<? extends Annotation>, Annotation>) annotations.get(targetClass);
System.out.println(map);
map.put(targetAnnotation, targetValue);
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,6 @@
package com.baeldung.java.reflection;
@Greeter(greet="Good morning")
public class Greetings {
}
@@ -0,0 +1,5 @@
package com.baeldung.java.reflection;
public interface Locomotion {
String getLocomotion();
}
@@ -0,0 +1,21 @@
package com.baeldung.java.reflection;
public class Operations {
public double publicSum(int a, double b) {
return a + b;
}
public static double publicStaticMultiply(float a, long b) {
return a * b;
}
private boolean privateAnd(boolean a, boolean b) {
return a && b;
}
protected int protectedMax(int a, int b) {
return a > b ? a : b;
}
}
@@ -0,0 +1,6 @@
package com.baeldung.java.reflection;
public class Person {
private String name;
private int age;
}
@@ -0,0 +1,5 @@
package com.baeldung.reflection.voidtype;
public interface Action {
void execute();
}
@@ -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);
}
}
@@ -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> V defer(Callable<V> callable) throws Exception {
return callable.call();
}
public static void defer(Runnable runnable) {
runnable.run();
}
public static <T, R> R defer(Function<T, R> function, T arg) {
return function.apply(arg);
}
public static <T> void defer(Consumer<T> consumer, T arg) {
consumer.accept(arg);
}
public static void defer(Action action) {
action.execute();
}
}
@@ -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<Void>() {
@Override
public Void call() {
runnable.run();
return null;
}
});
}
}
@@ -0,0 +1,57 @@
package com.baeldung.dynamicproxy;
import org.junit.Test;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class DynamicProxyIntegrationTest {
@Test
public void givenDynamicProxy_thenPutWorks() {
Map proxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyIntegrationTest.class.getClassLoader(), new Class[] { Map.class }, new DynamicInvocationHandler());
proxyInstance.put("hello", "world");
}
@Test
public void givenInlineDynamicProxy_thenGetWorksOtherMethodsDoNot() {
Map proxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyIntegrationTest.class.getClassLoader(), new Class[] { Map.class }, (proxy, method, methodArgs) -> {
if (method.getName().equals("get")) {
return 42;
} else {
throw new UnsupportedOperationException("Unsupported method: " + method.getName());
}
});
int result = (int) proxyInstance.get("hello");
assertEquals(42, result);
try {
proxyInstance.put("hello", "world");
fail();
} catch(UnsupportedOperationException e) {
// expected
}
}
@Test
public void givenTimingDynamicProxy_thenMethodInvokationsProduceTiming() {
Map mapProxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyIntegrationTest.class.getClassLoader(), new Class[] { Map.class }, new TimingDynamicInvocationHandler(new HashMap<>()));
mapProxyInstance.put("hello", "world");
assertEquals("world", mapProxyInstance.get("hello"));
CharSequence csProxyInstance = (CharSequence) Proxy.newProxyInstance(DynamicProxyIntegrationTest.class.getClassLoader(), new Class[] { CharSequence.class }, new TimingDynamicInvocationHandler("Hello World"));
assertEquals('l', csProxyInstance.charAt(2));
assertEquals(11, csProxyInstance.length());
}
}
@@ -0,0 +1,34 @@
package com.baeldung.reflect;
import static org.assertj.core.api.Assertions.assertThat;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
public class MethodParamNameUnitTest {
@Test
public void whenGetConstructorParams_thenOk()
throws NoSuchMethodException, SecurityException {
List<Parameter> parameters
= Arrays.asList(Person.class.getConstructor(String.class).getParameters());
Optional<Parameter> parameter
= parameters.stream().filter(Parameter::isNamePresent).findFirst();
assertThat(parameter.get().getName()).isEqualTo("fullName");
}
@Test
public void whenGetMethodParams_thenOk()
throws NoSuchMethodException, SecurityException {
List<Parameter> parameters
= Arrays.asList(
Person.class.getMethod("setFullName", String.class).getParameters());
Optional<Parameter> parameter
= parameters.stream().filter(Parameter::isNamePresent).findFirst();
assertThat(parameter.get().getName()).isEqualTo("fullName");
}
}
@@ -0,0 +1,24 @@
package com.baeldung.reflection;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertTrue;
public class BaeldungReflectionUtilsUnitTest {
@Test
public void givenCustomer_whenAFieldIsNull_thenFieldNameInResult() throws Exception {
Customer customer = new Customer(1, "Himanshu", null, null);
List<String> result = BaeldungReflectionUtils.getNullPropertiesList(customer);
List<String> expectedFieldNames = Arrays.asList("emailId", "phoneNumber");
assertTrue(result.size() == expectedFieldNames.size());
assertTrue(result.containsAll(expectedFieldNames));
}
}
@@ -0,0 +1,150 @@
package com.baeldung.reflection;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.*;
public class PersonAndEmployeeReflectionUnitTest {
// Fields names
private static final String LAST_NAME_FIELD = "lastName";
private static final String FIRST_NAME_FIELD = "firstName";
private static final String EMPLOYEE_ID_FIELD = "employeeId";
private static final String MONTH_EMPLOYEE_REWARD_FIELD = "reward";
@Test
public void givenPersonClass_whenGetDeclaredFields_thenTwoFields() {
// When
Field[] allFields = Person.class.getDeclaredFields();
// Then
assertEquals(2, allFields.length);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(LAST_NAME_FIELD)
&& field.getType().equals(String.class))
);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(FIRST_NAME_FIELD)
&& field.getType().equals(String.class))
);
}
@Test
public void givenEmployeeClass_whenGetDeclaredFields_thenOneField() {
// When
Field[] allFields = Employee.class.getDeclaredFields();
// Then
assertEquals(1, allFields.length);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(EMPLOYEE_ID_FIELD)
&& field.getType().equals(int.class))
);
}
@Test
public void givenEmployeeClass_whenSuperClassGetDeclaredFields_thenOneField() {
// When
Field[] allFields = Employee.class.getSuperclass().getDeclaredFields();
// Then
assertEquals(2, allFields.length);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(LAST_NAME_FIELD)
&& field.getType().equals(String.class))
);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(FIRST_NAME_FIELD)
&& field.getType().equals(String.class))
);
}
@Test
public void givenEmployeeClass_whenGetDeclaredFieldsOnBothClasses_thenThreeFields() {
// When
Field[] personFields = Employee.class.getSuperclass().getDeclaredFields();
Field[] employeeFields = Employee.class.getDeclaredFields();
Field[] allFields = new Field[employeeFields.length + personFields.length];
Arrays.setAll(allFields, i -> (i < personFields.length ? personFields[i] : employeeFields[i - personFields.length]));
// Then
assertEquals(3, allFields.length);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(LAST_NAME_FIELD)
&& field.getType().equals(String.class))
);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(FIRST_NAME_FIELD)
&& field.getType().equals(String.class))
);
assertTrue(Arrays.stream(allFields).anyMatch(field ->
field.getName().equals(EMPLOYEE_ID_FIELD)
&& field.getType().equals(int.class))
);
}
@Test
public void givenEmployeeClass_whenGetDeclaredFieldsOnEmployeeSuperclassWithModifiersFilter_thenOneFields() {
// When
List<Field> personFields = Arrays.stream(Employee.class.getSuperclass().getDeclaredFields())
.filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers()))
.collect(Collectors.toList());
// Then
assertEquals(1, personFields.size());
assertTrue(personFields.stream().anyMatch(field ->
field.getName().equals(LAST_NAME_FIELD)
&& field.getType().equals(String.class))
);
}
@Test
public void givenMonthEmployeeClass_whenGetAllFields_thenThreeFields() {
// When
List<Field> allFields = getAllFields(MonthEmployee.class);
// Then
assertEquals(3, allFields.size());
assertTrue(allFields.stream().anyMatch(field ->
field.getName().equals(LAST_NAME_FIELD)
&& field.getType().equals(String.class))
);
assertTrue(allFields.stream().anyMatch(field ->
field.getName().equals(EMPLOYEE_ID_FIELD)
&& field.getType().equals(int.class))
);
assertTrue(allFields.stream().anyMatch(field ->
field.getName().equals(MONTH_EMPLOYEE_REWARD_FIELD)
&& field.getType().equals(double.class))
);
}
public List<Field> getAllFields(Class clazz) {
if (clazz == null) {
return Collections.emptyList();
}
List<Field> result = new ArrayList<>(getAllFields(clazz.getSuperclass()));
List<Field> filteredFields = Arrays.stream(clazz.getDeclaredFields())
.filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers()))
.collect(Collectors.toList());
result.addAll(filteredFields);
return result;
}
}
@@ -0,0 +1,57 @@
package com.baeldung.java.reflection;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
public class OperationsUnitTest {
public OperationsUnitTest() {
}
@Test(expected = IllegalAccessException.class)
public void givenObject_whenInvokePrivateMethod_thenFail() throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method andPrivateMethod = Operations.class.getDeclaredMethod("privateAnd", boolean.class, boolean.class);
Operations operationsInstance = new Operations();
Boolean result = (Boolean) andPrivateMethod.invoke(operationsInstance, true, false);
assertFalse(result);
}
@Test
public void givenObject_whenInvokePrivateMethod_thenCorrect() throws Exception {
Method andPrivatedMethod = Operations.class.getDeclaredMethod("privateAnd", boolean.class, boolean.class);
andPrivatedMethod.setAccessible(true);
Operations operationsInstance = new Operations();
Boolean result = (Boolean) andPrivatedMethod.invoke(operationsInstance, true, false);
assertFalse(result);
}
@Test
public void givenObject_whenInvokePublicMethod_thenCorrect() throws Exception {
Method sumInstanceMethod = Operations.class.getMethod("publicSum", int.class, double.class);
Operations operationsInstance = new Operations();
Double result = (Double) sumInstanceMethod.invoke(operationsInstance, 1, 3);
assertThat(result, equalTo(4.0));
}
@Test
public void givenObject_whenInvokeStaticMethod_thenCorrect() throws Exception {
Method multiplyStaticMethod = Operations.class.getDeclaredMethod("publicStaticMultiply", float.class, long.class);
Double result = (Double) multiplyStaticMethod.invoke(null, 3.5f, 2);
assertThat(result, equalTo(7.0));
}
}
@@ -0,0 +1,302 @@
package com.baeldung.java.reflection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class ReflectionUnitTest {
@Test
public void givenObject_whenGetsFieldNamesAtRuntime_thenCorrect() {
final Object person = new Person();
final Field[] fields = person.getClass().getDeclaredFields();
final List<String> actualFieldNames = getFieldNames(fields);
assertTrue(Arrays.asList("name", "age").containsAll(actualFieldNames));
}
@Test
public void givenObject_whenGetsClassName_thenCorrect() {
final Object goat = new Goat("goat");
final Class<?> clazz = goat.getClass();
assertEquals("Goat", clazz.getSimpleName());
assertEquals("com.baeldung.java.reflection.Goat", clazz.getName());
assertEquals("com.baeldung.java.reflection.Goat", clazz.getCanonicalName());
}
@Test
public void givenClassName_whenCreatesObject_thenCorrect() throws ClassNotFoundException {
final Class<?> clazz = Class.forName("com.baeldung.java.reflection.Goat");
assertEquals("Goat", clazz.getSimpleName());
assertEquals("com.baeldung.java.reflection.Goat", clazz.getName());
assertEquals("com.baeldung.java.reflection.Goat", clazz.getCanonicalName());
}
@Test
public void givenClass_whenRecognisesModifiers_thenCorrect() throws ClassNotFoundException {
final Class<?> goatClass = Class.forName("com.baeldung.java.reflection.Goat");
final Class<?> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
final int goatMods = goatClass.getModifiers();
final int animalMods = animalClass.getModifiers();
assertTrue(Modifier.isPublic(goatMods));
assertTrue(Modifier.isAbstract(animalMods));
assertTrue(Modifier.isPublic(animalMods));
}
@Test
public void givenClass_whenGetsPackageInfo_thenCorrect() {
final Goat goat = new Goat("goat");
final Class<?> goatClass = goat.getClass();
final Package pkg = goatClass.getPackage();
assertEquals("com.baeldung.java.reflection", pkg.getName());
}
@Test
public void givenClass_whenGetsSuperClass_thenCorrect() {
final Goat goat = new Goat("goat");
final String str = "any string";
final Class<?> goatClass = goat.getClass();
final Class<?> goatSuperClass = goatClass.getSuperclass();
assertEquals("Animal", goatSuperClass.getSimpleName());
assertEquals("Object", str.getClass().getSuperclass().getSimpleName());
}
@Test
public void givenClass_whenGetsImplementedInterfaces_thenCorrect() throws ClassNotFoundException {
final Class<?> goatClass = Class.forName("com.baeldung.java.reflection.Goat");
final Class<?> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
final Class<?>[] goatInterfaces = goatClass.getInterfaces();
final Class<?>[] animalInterfaces = animalClass.getInterfaces();
assertEquals(1, goatInterfaces.length);
assertEquals(1, animalInterfaces.length);
assertEquals("Locomotion", goatInterfaces[0].getSimpleName());
assertEquals("Eating", animalInterfaces[0].getSimpleName());
}
@Test
public void givenClass_whenGetsConstructor_thenCorrect() throws ClassNotFoundException {
final Class<?> goatClass = Class.forName("com.baeldung.java.reflection.Goat");
final Constructor<?>[] constructors = goatClass.getConstructors();
assertEquals(1, constructors.length);
assertEquals("com.baeldung.java.reflection.Goat", constructors[0].getName());
}
@Test
public void givenClass_whenGetsFields_thenCorrect() throws ClassNotFoundException {
final Class<?> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
final Field[] fields = animalClass.getDeclaredFields();
final List<String> actualFields = getFieldNames(fields);
assertEquals(2, actualFields.size());
assertTrue(actualFields.containsAll(Arrays.asList("name", "CATEGORY")));
}
@Test
public void givenClass_whenGetsMethods_thenCorrect() throws ClassNotFoundException {
final Class<?> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
final Method[] methods = animalClass.getDeclaredMethods();
final List<String> actualMethods = getMethodNames(methods);
assertEquals(3, actualMethods.size());
assertTrue(actualMethods.containsAll(Arrays.asList("getName", "setName", "getSound")));
}
@Test
public void givenClass_whenGetsAllConstructors_thenCorrect() throws ClassNotFoundException {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Constructor<?>[] constructors = birdClass.getConstructors();
assertEquals(3, constructors.length);
}
@Test
public void givenClass_whenGetsEachConstructorByParamTypes_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
birdClass.getConstructor();
birdClass.getConstructor(String.class);
birdClass.getConstructor(String.class, boolean.class);
}
@Test
public void givenClass_whenInstantiatesObjectsAtRuntime_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Constructor<?> cons1 = birdClass.getConstructor();
final Constructor<?> cons2 = birdClass.getConstructor(String.class);
final Constructor<?> cons3 = birdClass.getConstructor(String.class, boolean.class);
final Bird bird1 = (Bird) cons1.newInstance();
final Bird bird2 = (Bird) cons2.newInstance("Weaver bird");
final Bird bird3 = (Bird) cons3.newInstance("dove", true);
assertEquals("bird", bird1.getName());
assertEquals("Weaver bird", bird2.getName());
assertEquals("dove", bird3.getName());
assertFalse(bird1.walks());
assertTrue(bird3.walks());
}
@Test
public void givenClass_whenGetsPublicFields_thenCorrect() throws ClassNotFoundException {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Field[] fields = birdClass.getFields();
assertEquals(1, fields.length);
assertEquals("CATEGORY", fields[0].getName());
}
@Test
public void givenClass_whenGetsPublicFieldByName_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Field field = birdClass.getField("CATEGORY");
assertEquals("CATEGORY", field.getName());
}
@Test
public void givenClass_whenGetsDeclaredFields_thenCorrect() throws ClassNotFoundException {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Field[] fields = birdClass.getDeclaredFields();
assertEquals(1, fields.length);
assertEquals("walks", fields[0].getName());
}
@Test
public void givenClass_whenGetsFieldsByName_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Field field = birdClass.getDeclaredField("walks");
assertEquals("walks", field.getName());
}
@Test
public void givenClassField_whenGetsType_thenCorrect() throws Exception {
final Field field = Class.forName("com.baeldung.java.reflection.Bird").getDeclaredField("walks");
final Class<?> fieldClass = field.getType();
assertEquals("boolean", fieldClass.getSimpleName());
}
@Test
public void givenClassField_whenSetsAndGetsValue_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Bird bird = (Bird) birdClass.newInstance();
final Field field = birdClass.getDeclaredField("walks");
field.setAccessible(true);
assertFalse(field.getBoolean(bird));
assertFalse(bird.walks());
field.set(bird, true);
assertTrue(field.getBoolean(bird));
assertTrue(bird.walks());
}
@Test
public void givenClassField_whenGetsAndSetsWithNull_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Field field = birdClass.getField("CATEGORY");
field.setAccessible(true);
assertEquals("domestic", field.get(null));
}
@Test
public void givenClass_whenGetsAllPublicMethods_thenCorrect() throws ClassNotFoundException {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Method[] methods = birdClass.getMethods();
final List<String> methodNames = getMethodNames(methods);
assertTrue(methodNames.containsAll(Arrays.asList("equals", "notifyAll", "hashCode", "walks", "eats", "toString")));
}
@Test
public void givenClass_whenGetsOnlyDeclaredMethods_thenCorrect() throws ClassNotFoundException {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final List<String> actualMethodNames = getMethodNames(birdClass.getDeclaredMethods());
final List<String> expectedMethodNames = Arrays.asList("setWalks", "walks", "getSound", "eats");
assertEquals(expectedMethodNames.size(), actualMethodNames.size());
assertTrue(expectedMethodNames.containsAll(actualMethodNames));
assertTrue(actualMethodNames.containsAll(expectedMethodNames));
}
@Test
public void givenMethodName_whenGetsMethod_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Method walksMethod = birdClass.getDeclaredMethod("walks");
final Method setWalksMethod = birdClass.getDeclaredMethod("setWalks", boolean.class);
assertFalse(walksMethod.isAccessible());
assertFalse(setWalksMethod.isAccessible());
walksMethod.setAccessible(true);
setWalksMethod.setAccessible(true);
assertTrue(walksMethod.isAccessible());
assertTrue(setWalksMethod.isAccessible());
}
@Test
public void givenMethod_whenInvokes_thenCorrect() throws Exception {
final Class<?> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
final Bird bird = (Bird) birdClass.newInstance();
final Method setWalksMethod = birdClass.getDeclaredMethod("setWalks", boolean.class);
final Method walksMethod = birdClass.getDeclaredMethod("walks");
final boolean walks = (boolean) walksMethod.invoke(bird);
assertFalse(walks);
assertFalse(bird.walks());
setWalksMethod.invoke(bird, true);
final boolean walks2 = (boolean) walksMethod.invoke(bird);
assertTrue(walks2);
assertTrue(bird.walks());
}
private static List<String> getFieldNames(Field[] fields) {
final List<String> fieldNames = new ArrayList<>();
for (final Field field : fields) {
fieldNames.add(field.getName());
}
return fieldNames;
}
private static List<String> getMethodNames(Method[] methods) {
final List<String> methodNames = new ArrayList<>();
for (final Method method : methods) {
methodNames.add(method.getName());
}
return methodNames;
}
}
@@ -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<Method> 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()));
}
}
@@ -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<Void> callable = new Callable<Void>() {
@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<String, Void> 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<String> 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());
}
}
@@ -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());
}
}