diff --git a/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/Unsafe.java b/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/Unsafe.java index 16b2d6b..2fd4336 100644 --- a/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/Unsafe.java +++ b/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/Unsafe.java @@ -5,6 +5,9 @@ import io.gitlab.jfronny.commons.throwable.Try; import java.lang.reflect.Field; import java.nio.ByteBuffer; +/** + * A wrapper for sun.misc.Unsafe + */ @SuppressWarnings({"unchecked", "unused"}) public class Unsafe { public static final sun.misc.Unsafe theUnsafe = Try.orThrow(() -> { diff --git a/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/LambdaFactory.java b/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/LambdaFactory.java index 2509b93..b2c6449 100644 --- a/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/LambdaFactory.java +++ b/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/LambdaFactory.java @@ -6,14 +6,30 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.function.*; +/** + * A class that wraps the LambdaMetafactory to more easily create lambdas from MethodHandles. + */ @SuppressWarnings("unchecked") public class LambdaFactory { private static final MethodHandles.Lookup LOOKUP_ROOT = MethodHandles.lookup(); + /** + * Creates a private lookup for the given class. + * @param klazz the class to create the lookup for + * @return a lookup for the given class + * @throws IllegalAccessException if the lookup cannot be created + */ public static MethodHandles.Lookup lookup(Class klazz) throws IllegalAccessException { return MethodHandles.privateLookupIn(klazz, LOOKUP_ROOT); } + /** + * Creates a new Runnable from the given handle. + * @param lookup the lookup to use + * @param handle the handle to create the lambda from + * @return a new Runnable that calls the given handle + * @throws Throwable if the lambda cannot be created + */ public static Runnable runnable(MethodHandles.Lookup lookup, MethodHandle handle) throws Throwable { return (Runnable) LambdaMetafactory.metafactory( lookup, @@ -25,6 +41,15 @@ public class LambdaFactory { ).getTarget().invoke(); } + /** + * Creates a new Consumer from the given handle. + * @param lookup the lookup to use + * @param handle the handle to create the lambda from + * @param parameterType the type of the parameter + * @param the type of the parameter + * @return a new Consumer that calls the given handle + * @throws Throwable if the lambda cannot be created + */ public static Consumer consumer(MethodHandles.Lookup lookup, MethodHandle handle, Class parameterType) throws Throwable { return (Consumer) LambdaMetafactory.metafactory( lookup, @@ -36,6 +61,17 @@ public class LambdaFactory { ).getTarget().invoke(); } + /** + * Creates a new BiConsumer from the given handle. + * @param lookup the lookup to use + * @param handle the handle to create the lambda from + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @return a new BiConsumer that calls the given handle + * @throws Throwable if the lambda cannot be created + */ public static BiConsumer consumer(MethodHandles.Lookup lookup, MethodHandle handle, Class parameterType1, Class parameterType2) throws Throwable { return (BiConsumer) LambdaMetafactory.metafactory( lookup, @@ -47,6 +83,15 @@ public class LambdaFactory { ).getTarget().invoke(); } + /** + * Creates a new Supplier from the given handle. + * @param lookup the lookup to use + * @param handle the handle to create the lambda from + * @param returnType the return type of the supplier + * @param the return type of the supplier + * @return a new Supplier that calls the given handle + * @throws Throwable if the lambda cannot be created + */ public static Supplier supplier(MethodHandles.Lookup lookup, MethodHandle handle, Class returnType) throws Throwable { return (Supplier) LambdaMetafactory.metafactory( lookup, @@ -58,6 +103,17 @@ public class LambdaFactory { ).getTarget().invoke(); } + /** + * Creates a new Function from the given handle. + * @param lookup the lookup to use + * @param handle the handle to create the lambda from + * @param returnType the return type of the function + * @param parameterType the type of the parameter + * @param the type of the parameter + * @param the return type of the function + * @return a new Function that calls the given handle + * @throws Throwable if the lambda cannot be created + */ public static Function function(MethodHandles.Lookup lookup, MethodHandle handle, Class returnType, Class parameterType) throws Throwable { return (Function) LambdaMetafactory.metafactory( lookup, @@ -69,6 +125,19 @@ public class LambdaFactory { ).getTarget().invoke(); } + /** + * Creates a new BiFunction from the given handle. + * @param lookup the lookup to use + * @param handle the handle to create the lambda from + * @param returnType the return type of the function + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @param the return type of the function + * @return a new BiFunction that calls the given handle + * @throws Throwable if the lambda cannot be created + */ public static BiFunction function(MethodHandles.Lookup lookup, MethodHandle handle, Class returnType, Class parameterType1, Class parameterType2) throws Throwable { return (BiFunction) LambdaMetafactory.metafactory( lookup, diff --git a/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/Reflect.java b/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/Reflect.java index bd769d2..efd248a 100644 --- a/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/Reflect.java +++ b/commons-unsafe/src/main/java/io/gitlab/jfronny/commons/unsafe/reflect/Reflect.java @@ -3,134 +3,378 @@ package io.gitlab.jfronny.commons.unsafe.reflect; import java.lang.invoke.MethodHandles; import java.util.function.*; +/** + * A class that provides a set of methods to create functional interfaces for reflective calls. + */ @SuppressWarnings("unchecked") public class Reflect { - // Constructor without parameters + /** + * Creates a supplier that constructs the given class using the default, no-arg constructor. + * @param toConstruct the class to construct + * @param the type of the class to construct + * @return a supplier that constructs the class + * @throws Throwable if an error occurs + */ public static Supplier constructor(Class toConstruct) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(toConstruct); return LambdaFactory.supplier(lookup, lookup.unreflectConstructor(toConstruct.getDeclaredConstructor()), toConstruct); } + /** + * Creates a supplier that constructs the given class using the default, no-arg constructor. + * @param targetClassName the name of the class to construct + * @param the type of the class to construct + * @return a supplier that constructs the class + * @throws Throwable if an error occurs + */ public static Supplier constructor(String targetClassName) throws Throwable { return (Supplier) constructor(Class.forName(targetClassName)); } - // Constructor with one parameter + /** + * Creates a function that constructs the given class using a constructor with one parameter. + * @param toConstruct the class to construct + * @param parameterType the type of the parameter + * @param the type of the parameter + * @param the type of the class to construct + * @return a function that constructs the class given a parameter + * @throws Throwable if an error occurs + */ public static Function constructor(Class toConstruct, Class parameterType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(toConstruct); return LambdaFactory.function(lookup, lookup.unreflectConstructor(toConstruct.getDeclaredConstructor(parameterType)), toConstruct, parameterType); } + /** + * Creates a function that constructs the given class using a constructor with one parameter. + * @param targetClassName the name of the class to construct + * @param parameterType the type of the parameter + * @param the type of the parameter + * @param the type of the class to construct + * @return a function that constructs the class given a parameter + * @throws Throwable if an error occurs + */ public static Function constructor(String targetClassName, Class parameterType) throws Throwable { return (Function) constructor(Class.forName(targetClassName), parameterType); } - // Constructor with two parameters + /** + * Creates a function that constructs the given class using a constructor with two parameters. + * @param toConstruct the class to construct + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @param the type of the class to construct + * @return a function that constructs the class given two parameters + * @throws Throwable if an error occurs + */ public static BiFunction constructor(Class toConstruct, Class parameterType1, Class parameterType2) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(toConstruct); return LambdaFactory.function(lookup, lookup.unreflectConstructor(toConstruct.getDeclaredConstructor(parameterType1, parameterType2)), toConstruct, parameterType1, parameterType2); } + /** + * Creates a function that constructs the given class using a constructor with two parameters. + * @param targetClassName the name of the class to construct + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @param the type of the class to construct + * @return a function that constructs the class given two parameters + * @throws Throwable if an error occurs + */ public static BiFunction constructor(String targetClassName, Class parameterType1, Class parameterType2) throws Throwable { return constructor((Class) Class.forName(targetClassName), parameterType1, parameterType2); } - // Procedure without parameters + /** + * Creates a runnable that calls the given static method, which returns void and takes no arguments. + * @param targetClass the class containing the method + * @param name the name of the method + * @return a runnable that calls the method + * @throws Throwable if an error occurs + */ public static Runnable staticProcedure(Class targetClass, String name) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.runnable(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name))); } + /** + * Creates a runnable that calls the given static method, which returns void and takes no arguments. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @return a runnable that calls the method + * @throws Throwable if an error occurs + */ public static Runnable staticProcedure(String targetClassName, String name) throws Throwable { return staticProcedure(Class.forName(targetClassName), name); } - // Procedure with one parameter + /** + * Creates a consumer that calls the given static method, which returns void and takes one argument. + * @param targetClass the class containing the method + * @param name the name of the method + * @param parameterType the type of the parameter + * @param the type of the parameter + * @return a consumer that calls the method + * @throws Throwable if an error occurs + */ public static Consumer staticProcedure(Class targetClass, String name, Class parameterType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.consumer(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name, parameterType)), parameterType); } + /** + * Creates a consumer that calls the given static method, which returns void and takes one argument. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param parameterType the type of the parameter + * @param the type of the parameter + * @return a consumer that calls the method + * @throws Throwable if an error occurs + */ public static Consumer staticProcedure(String targetClassName, String name, Class parameterType) throws Throwable { return staticProcedure(Class.forName(targetClassName), name, parameterType); } - // Procedure with two parameters + /** + * Creates a consumer that calls the given static method, which returns void and takes two arguments. + * @param targetClass the class containing the method + * @param name the name of the method + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @return a consumer that calls the method + * @throws Throwable if an error occurs + */ public static BiConsumer staticProcedure(Class targetClass, String name, Class parameterType1, Class parameterType2) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.consumer(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name, parameterType1, parameterType2)), parameterType1, parameterType2); } + /** + * Creates a consumer that calls the given static method, which returns void and takes two arguments. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @return a consumer that calls the method + * @throws Throwable if an error occurs + */ public static BiConsumer staticProcedure(String targetClassName, String name, Class parameterType1, Class parameterType2) throws Throwable { return staticProcedure(Class.forName(targetClassName), name, parameterType1, parameterType2); } - // Function without parameters + /** + * Creates a supplier that calls the given static method, which returns a value and takes no arguments. + * @param targetClass the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param the return type of the method + * @return a supplier that calls the method + * @throws Throwable if an error occurs + */ public static Supplier staticFunction(Class targetClass, String name, Class returnType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.supplier(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name)), returnType); } + /** + * Creates a supplier that calls the given static method, which returns a value and takes no arguments. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param the return type of the method + * @return a supplier that calls the method + * @throws Throwable if an error occurs + */ public static Supplier staticFunction(String targetClassName, String name, Class returnType) throws Throwable { return staticFunction(Class.forName(targetClassName), name, returnType); } - // Function with one parameter + /** + * Creates a function that calls the given static method, which returns a value and takes one argument. + * @param targetClass the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param parameterType the type of the parameter + * @param the type of the parameter + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static Function staticFunction(Class targetClass, String name, Class returnType, Class parameterType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.function(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name, parameterType)), returnType, parameterType); } + /** + * Creates a function that calls the given static method, which returns a value and takes one argument. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param parameterType the type of the parameter + * @param the type of the parameter + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static Function staticFunction(String targetClassName, String name, Class returnType, Class parameterType) throws Throwable { return staticFunction(Class.forName(targetClassName), name, returnType, parameterType); } - // Function with two parameters + /** + * Creates a function that calls the given static method, which returns a value and takes two arguments. + * @param targetClass the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static BiFunction staticFunction(Class targetClass, String name, Class returnType, Class parameterType1, Class parameterType2) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.function(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name, parameterType1, parameterType2)), returnType, parameterType1, parameterType2); } + /** + * Creates a function that calls the given static method, which returns a value and takes two arguments. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param parameterType1 the type of the first parameter + * @param parameterType2 the type of the second parameter + * @param the type of the first parameter + * @param the type of the second parameter + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static BiFunction staticFunction(String targetClassName, String name, Class returnType, Class parameterType1, Class parameterType2) throws Throwable { return staticFunction(Class.forName(targetClassName), name, returnType, parameterType1, parameterType2); } - // Procedure without parameters + /** + * Creates a consumer that calls the given instance method, which returns void and takes no arguments. + * @param targetClass the class containing the method + * @param name the name of the method + * @param the type of the class containing the method + * @return a supplier that constructs the class + * @throws Throwable if an error occurs + */ public static Consumer instanceProcedure(Class targetClass, String name) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.consumer(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name)), targetClass); } + /** + * Creates a consumer that calls the given instance method, which returns void and takes no arguments. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param the type of the class containing the method + * @return a supplier that constructs the class + * @throws Throwable if an error occurs + */ public static Consumer instanceProcedure(String targetClassName, String name) throws Throwable { return (Consumer) instanceProcedure(Class.forName(targetClassName), name); } - // Procedure with one parameter + /** + * Creates a consumer that calls the given instance method, which returns void and takes one argument. + * @param targetClass the class containing the method + * @param name the name of the method + * @param parameterType the type of the parameter + * @param the type of the class containing the method + * @param the type of the parameter + * @return a consumer that calls the method + * @throws Throwable if an error occurs + */ public static BiConsumer instanceProcedure(Class targetClass, String name, Class parameterType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.consumer(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name, parameterType)), targetClass, parameterType); } + /** + * Creates a consumer that calls the given instance method, which returns void and takes one argument. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param parameterType the type of the parameter + * @param the type of the class containing the method + * @param the type of the parameter + * @return a consumer that calls the method + * @throws Throwable if an error occurs + */ public static BiConsumer instanceProcedure(String targetClassName, String name, Class parameterType) throws Throwable { return (BiConsumer) instanceProcedure(Class.forName(targetClassName), name, parameterType); } - // Function without parameters + /** + * Creates a function that calls the given instance method, which returns a value and takes no arguments. + * @param targetClass the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param the type of the class containing the method + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static Function instanceFunction(Class targetClass, String name, Class returnType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.function(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name)), returnType, targetClass); } + /** + * Creates a function that calls the given instance method, which returns a value and takes no arguments. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param the type of the class containing the method + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static Function instanceFunction(String targetClassName, String name, Class returnType) throws Throwable { return (Function) instanceFunction(Class.forName(targetClassName), name, returnType); } - // Function with one parameter + /** + * Creates a function that calls the given instance method, which returns a value and takes one argument. + * @param targetClass the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param parameterType the type of the parameter + * @param the type of the class containing the method + * @param the type of the parameter + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static BiFunction instanceFunction(Class targetClass, String name, Class returnType, Class parameterType) throws Throwable { MethodHandles.Lookup lookup = LambdaFactory.lookup(targetClass); return LambdaFactory.function(lookup, lookup.unreflect(targetClass.getDeclaredMethod(name, parameterType)), returnType, targetClass, parameterType); } + /** + * Creates a function that calls the given instance method, which returns a value and takes one argument. + * @param targetClassName the name of the class containing the method + * @param name the name of the method + * @param returnType the return type of the method + * @param parameterType the type of the parameter + * @param the type of the class containing the method + * @param the type of the parameter + * @param the return type of the method + * @return a function that calls the method + * @throws Throwable if an error occurs + */ public static BiFunction instanceFunction(String targetClassName, String name, Class returnType, Class parameterType) throws Throwable { return (BiFunction) instanceFunction(Class.forName(targetClassName), name, returnType, parameterType); }