AbyssalLib Help

Reflection API

The AbyssalLib Reflection API is a high-performance, cached wrapper around standard Java Reflection and MethodHandles. It abstracts away accessibility checks (setAccessible(true)) and uses a Result<T> wrapper to eliminate standard checked exceptions.

The Result Wrapper

All operations that can fail (such as finding a method or getting a field value) return a Result<T> instead of throwing checked exceptions.

Method

Information

get()

Returns the value, or throws a RuntimeException if the operation failed.

getOrNull()

Returns the value, or null if the operation failed.

getOrElse(T fallback)

Returns the value, or the provided fallback if it failed.

ifSuccess(Consumer<T>)

Executes the consumer block only if the operation was successful.

ifFailure(Consumer<Throwable>)

Executes the consumer block only if the operation failed, passing the exception.

map(Function)/flatMap(Function)

Transforms the result functionally, chaining reflection calls together safely.

Accessing Classes

The entry point for the API is the Reflect class. Internal caching ensures that repeated lookups for the same class or member do not incur a performance penalty.

// From a known class (Never fails, returns directly) ReflectClass<Player> refPlayer = Reflect.of(Player.class); // From a string (Returns a Result) Result<ReflectClass<?>> refEntity = Reflect.of("net.minecraft.world.entity.Entity");
try { Class<?> clazz = Class.forName("net.minecraft.world.entity.Entity"); } catch (ClassNotFoundException e) { e.printStackTrace(); }

Fields

You can retrieve fields by their exact string name, or dynamically search the class hierarchy for the first field matching a specific Class type using fieldByType.

ReflectClass<?> clazz = Reflect.of(target.getClass()); // Get String value = (String) clazz.field("privateString") .flatMap(f -> f.get(target)) .getOrNull(); // Set clazz.field("privateString").ifSuccess(f -> f.set(target, "New Value")); // Look up by Type instead of name clazz.fieldByType(String.class).ifSuccess(f -> f.set(target, "New Value"));
try { Field field = target.getClass().getDeclaredField("privateString"); field.setAccessible(true); // Get String value = (String) field.get(target); // Set field.set(target, "New Value"); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); }

Methods

Methods are looked up using their name and their exact parameter types.

Reflect.of(target.getClass()) .method("doSomething", int.class, String.class) .ifSuccess(m -> { boolean result = (boolean) m.invoke(target, 5, "Hello").getOrElse(false); });
try { Method method = target.getClass().getDeclaredMethod("doSomething", int.class, String.class); method.setAccessible(true); boolean result = (boolean) method.invoke(target, 5, "Hello"); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }

Constructors

Constructors are fetched using their exact parameter types and can be instantiated safely.

ItemStack stack = Reflect.of(ItemStack.class) .constructor(Material.class, int.class) .flatMap(c -> c.newInstance(Material.DIAMOND, 64)) .getOrNull();
try { Constructor<ItemStack> constructor = ItemStack.class.getDeclaredConstructor(Material.class, int.class); constructor.setAccessible(true); ItemStack stack = constructor.newInstance(Material.DIAMOND, 64); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }

Arrays (ReflectArray)

Provides a safe wrapper over java.lang.reflect.Array to instantiate, read, and write arrays dynamically without manual casting or try-catch blocks.

ReflectArray.newInstance(String.class, 10).ifSuccess(array -> { ReflectArray.set(array, 0, "Hello"); String value = (String) ReflectArray.get(array, 0).getOrNull(); int length = ReflectArray.getLength(array).getOrElse(0); });
try { Object array = Array.newInstance(String.class, 10); Array.set(array, 0, "Hello"); String value = (String) Array.get(array, 0); int length = Array.getLength(array); } catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) { e.printStackTrace(); }

Generics and Types (ReflectType)

ReflectType wraps standard Java Type objects to easily resolve generic parameters, wildcards, and array components without manual instanceof checks.

Reflect.of(MyClass.class).field("stringList").ifSuccess(field -> { // Fetches the 'String' class from inside a List<String> field ReflectType genericType = field.getGenericType(); if (genericType.isParameterized()) { genericType.getTypeArguments().forEach(typeArg -> { Class<?> rawClass = typeArg.getRawType().getOrNull().getUnderlyingClass(); }); } });

Annotations (ReflectAnnotation)

Allows safe reading of annotation attributes at runtime without directly invoking the annotation's underlying interface methods.

Reflect.of(targetClass) .getReflectAnnotation(MyAnnotation.class) .ifSuccess(ann -> { // Safe dynamic retrieval of the default "value()" attribute String value = (String) ann.value().getOrNull(); // Safe dynamic retrieval of a custom attribute int priority = (int) ann.getValue("priority").getOrElse(0); });
try { MyAnnotation ann = targetClass.getAnnotation(MyAnnotation.class); if (ann != null) { Method valueMethod = ann.annotationType().getDeclaredMethod("value"); String value = (String) valueMethod.invoke(ann); } } catch (Exception e) { e.printStackTrace(); }
05 June 2026