Skip to content

Commit

Permalink
feat: use generic on Class types in ClassUtil
Browse files Browse the repository at this point in the history
This resolves #221
  • Loading branch information
JarvisCraft committed Aug 18, 2021
1 parent 4924d11 commit c3226f5
Showing 1 changed file with 20 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.util.function.Function;
import java.util.stream.Stream;

import static ru.progrm_jarvis.javacommons.unchecked.UncheckedCasts.uncheckedClassCast;

/**
* Utility for class-related stuff.
*/
Expand Down Expand Up @@ -121,47 +123,52 @@ public boolean isPrimitiveWrapper(final Class<?> clazz) {
* Gets a primitive-wrapper class for the given primitive class.
*
* @param primitiveClass primitive class whose wrapper is needed
* @param <T> specific class type
* @return primitive-wrapper class for the given primitive class
*
* @throws IllegalArgumentException if the given class is not primitive
*/
public @NotNull Class<?> toPrimitiveWrapper(final @NotNull /* hot spot */ Class<?> primitiveClass) {
public <T> @NotNull Class<? extends T> toPrimitiveWrapper(final @NotNull Class<? super T> primitiveClass) {
final int primitiveClassIndex;
if ((primitiveClassIndex = Arrays.binarySearch(
SORTED_PRIMITIVE_CLASSES, primitiveClass, CLASS_HASH_CODE_COMPARATOR
)) < 0) throw new IllegalArgumentException("Given class is not primitive");

return PRIMITIVE_WRAPPER_CLASSES_SORTED_BY_PRIMITIVE_CLASSES[primitiveClassIndex];
return uncheckedClassCast(PRIMITIVE_WRAPPER_CLASSES_SORTED_BY_PRIMITIVE_CLASSES[primitiveClassIndex]);
}

/**
* Either returns a primitive-wrapper class for the given one if it is primitive or the provided class otherwise.
*
* @param originalClass class whose wrapper should be returned on demand
* @param <T> specific class type
* @return primitive-wrapper class for the given class if it is primitive or the provided class otherwise
*/
public @NotNull Class<?> toNonPrimitive(final @NotNull /* hot spot */ Class<?> originalClass) {
public <T> @NotNull Class<? extends T> toNonPrimitive(final @NotNull Class<? super T> originalClass) {
final int primitiveClassIndex;
return (primitiveClassIndex = Arrays.binarySearch(
SORTED_PRIMITIVE_CLASSES, originalClass, CLASS_HASH_CODE_COMPARATOR
)) < 0 ? originalClass : PRIMITIVE_WRAPPER_CLASSES_SORTED_BY_PRIMITIVE_CLASSES[primitiveClassIndex];
return uncheckedClassCast(
(primitiveClassIndex = Arrays.binarySearch(
SORTED_PRIMITIVE_CLASSES, originalClass, CLASS_HASH_CODE_COMPARATOR
)) < 0 ? originalClass : PRIMITIVE_WRAPPER_CLASSES_SORTED_BY_PRIMITIVE_CLASSES[primitiveClassIndex]
);
}

/**
* Gets a primitive class for the given primitive-wrapper class.
*
* @param primitiveWrapperClass primitive-wrapper class whose wrapper is needed
* @param <T> specific class type
* @return primitive class for the given primitive-wrapper class
*
* @throws IllegalArgumentException if the given class is not a primitive-wrapper
*/
public Class<?> toPrimitive(@NotNull /* hot spot */ final Class<?> primitiveWrapperClass) {
public <T> @NotNull Class<? extends T> toPrimitive(final @NotNull Class<? super T> primitiveWrapperClass) {
final int primitiveClassIndex;
if ((primitiveClassIndex = Arrays.binarySearch(
SORTED_PRIMITIVE_WRAPPER_CLASSES, primitiveWrapperClass, CLASS_HASH_CODE_COMPARATOR
)) < 0) throw new IllegalArgumentException("Given class is not a primitive-wrapper");

return PRIMITIVE_CLASSES_SORTED_BY_PRIMITIVE_WRAPPER_CLASSES[primitiveClassIndex];
return uncheckedClassCast(PRIMITIVE_CLASSES_SORTED_BY_PRIMITIVE_WRAPPER_CLASSES[primitiveClassIndex]);
}

/**
Expand All @@ -172,15 +179,16 @@ public Class<?> toPrimitive(@NotNull /* hot spot */ final Class<?> primitiveWrap
*
* @param original original type which should be integrated to the target type
* @param target target type to which the original type should be integrated
* @param <T> specific class type
* @return result of type integration, my be the same as original type
*
* @throws IllegalArgumentException if original type cannot be integrated to the target type
*/
public Class<?> integrateType(final @NotNull /* hot spot */ Class<?> original,
final @NotNull /* hot spot */ Class<?> target) {
public <T> Class<? extends T> integrateType(final @NotNull Class<? super T> original,
final @NotNull Class<? super T> target) {
// As `Class#isAssignableFrom()` is an intrinsic candidate
// there is no need for simple `==` check which is probably included in it
if (target.isAssignableFrom(original)) return original;
if (target.isAssignableFrom(original)) return uncheckedClassCast(original);

if(!original.isPrimitive()) throw new IllegalArgumentException(
"Original type " + original + " cannot be integrated with the target type " + target
Expand All @@ -193,7 +201,7 @@ public Class<?> integrateType(final @NotNull /* hot spot */ Class<?> original,
+ " cannot be integrated with target type " + target
);

return wrapper;
return uncheckedClassCast(wrapper);
}

/**
Expand Down

0 comments on commit c3226f5

Please sign in to comment.