Skip to content

Commit

Permalink
Don't wrap constructor in Optional because it doesn't play well with …
Browse files Browse the repository at this point in the history
…wildcards
  • Loading branch information
ljacqu committed Oct 5, 2024
1 parent 3f63cec commit cd7adc1
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 11 deletions.
15 changes: 9 additions & 6 deletions src/main/java/ch/jalu/typeresolver/reflect/ConstructorUtils.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package ch.jalu.typeresolver.reflect;

import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Collectors;

/**
Expand All @@ -14,18 +15,20 @@ private ConstructorUtils() {
}

/**
* Returns the specified constructor if it exists, otherwise returns an empty Optional.
* Returns the specified constructor if it exists, otherwise null.
*
* @param clazz the class to search in
* @param parameterTypes the parameter types the constructor must match
* @param <T> class type
* @return optional with the matching constructor, or empty optional
* @return the matching constructor, or null
*/
public static <T> Optional<Constructor<T>> tryFindConstructor(Class<T> clazz, Class<?>... parameterTypes) {
// Optional<Constructor<T>> would be a nicer return type, but generics don't play well when the incoming `clazz`
// parameter is typed as Class<?>
public static <T> @Nullable Constructor<T> getConstructorOrNull(Class<T> clazz, Class<?>... parameterTypes) {
try {
return Optional.of(clazz.getDeclaredConstructor(parameterTypes));
return clazz.getDeclaredConstructor(parameterTypes);
} catch (NoSuchMethodException ignore) {
return Optional.empty();
return null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Optional;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
Expand All @@ -20,12 +20,24 @@ class ConstructorUtilsTest {
@Test
void shouldReturnConstructorIfApplicable() throws NoSuchMethodException {
// given / when
Optional<Constructor<Sample>> constr1 = ConstructorUtils.tryFindConstructor(Sample.class, int.class, String.class);
Optional<Constructor<Sample>> constr2 = ConstructorUtils.tryFindConstructor(Sample.class, int.class, long.class);
Constructor<Sample> constr1 = ConstructorUtils.getConstructorOrNull(Sample.class, int.class, String.class);
Constructor<Sample> constr2 = ConstructorUtils.getConstructorOrNull(Sample.class, int.class, long.class);

// then
assertThat(constr1, equalTo(Optional.of(Sample.class.getDeclaredConstructor(int.class, String.class))));
assertThat(constr2, equalTo(Optional.empty()));
assertThat(constr1, equalTo(Sample.class.getDeclaredConstructor(int.class, String.class)));
assertThat(constr2, nullValue());
}

@Test
void shouldCompileWithWildcard() {
// given
Class<?> clazz = Sample.class;

// when
Constructor<?> result = ConstructorUtils.getConstructorOrNull(clazz, String[].class);

// then
assertThat(result, nullValue());
}

@Test
Expand Down

0 comments on commit cd7adc1

Please sign in to comment.