Package manifold.util
Class ReflectUtil
- java.lang.Object
-
- manifold.util.ReflectUtil
-
public class ReflectUtil extends Object
A Java reflection utility. Use it to efficiently access classes by name, get/set field values, invoke methods, and use constructors. Notable features include:- Intuitive, fluent API
- Call any method: private, filtered, inaccessible, etc.
- Get and set the value of a final field
- Access fields and methods of a class belonging to an inaccessible module
- Call a super method
- Call a default interface method esp. for a proxy
- Call a method structurally with automatic best method matching
- Fields, methods, and constructors are cached upon use to improve performance
- Works with all versions of Java beginning with Java 8
(Use @Jailbreak to avoid writing reflection code. See Type-safe Reflection.)
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classReflectUtil.ConstructorRefstatic classReflectUtil.FakeProxystatic classReflectUtil.FieldRefstatic classReflectUtil.LiveFieldRefstatic classReflectUtil.LiveMethodRefstatic classReflectUtil.MethodRefstatic classReflectUtil.WithNullUse to access live methods and fields with possible null return value if not found
-
Constructor Summary
Constructors Constructor Description ReflectUtil()
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static booleanarePrimitiveTypesAssignable(Class toType, Class fromType)static ReflectUtil.ConstructorRefconstructor(Class<?> cls, Class<?>... params)Get aReflectUtil.ConstructorRefto the specified constructor.static ReflectUtil.ConstructorRefconstructor(String fqn, Class<?>... params)Get aReflectUtil.ConstructorRefto the specified constructor.static ReflectUtil.FieldReffield(Class<?> cls, String name)Get aReflectUtil.FieldRefto the specified field.static ReflectUtil.LiveFieldReffield(Object receiver, String name)Get aReflectUtil.LiveFieldRefto the specified field.static ReflectUtil.FieldReffield(String fqn, String name)Get aReflectUtil.FieldRefto the specified field.static List<ReflectUtil.LiveFieldRef>fields(Object receiver)Visit declared fields of thereceiverclass.static List<ReflectUtil.LiveFieldRef>fields(Object receiver, Predicate<ReflectUtil.LiveFieldRef> filter)static MethodfindBestMethod(Method structMethod, Class receiverClass)static ObjectinvokeDefault(Object receiver, Class<?> iface, String name, Class<?>[] params, Object... args)This method behaves like the one below it, except this method ensures theifacedefault method is called even if thereceiveroverrides it.static ObjectinvokeDefault(Object receiver, Method method, Object... args)Invoke a default interface method.static ReflectUtil.MethodReflambdaMethod(Class<?> lambdaClass)Get aReflectUtil.MethodRefcorresponding with the functional interface implemented bylambdaClass.static ReflectUtil.MethodRefmethod(Class<?> cls, String name, Class... params)Get aReflectUtil.MethodRefto the specified method.static ReflectUtil.LiveMethodRefmethod(Object receiver, String name, Class... params)Get aReflectUtil.LiveMethodRefto the specified method.static ReflectUtil.MethodRefmethod(String fqn, String name, Class... params)Get aReflectUtil.MethodRefto the specified method.static ReflectUtil.MethodRefmethodFromName(Class<?> cls, String name)Get aReflectUtil.MethodRefto the specifiednamewithout regard to parameter types.static voidpreloadClassIntoParentLoader(String fqn, URI content, ClassLoader wouldBeLoader, ClassLoader parentLoader)Force class with namefqnto be loaded byparentLoader.static voidsetAccessible(Constructor c)static voidsetAccessible(Field f)static voidsetAccessible(Member m)static voidsetAccessible(Method m)static voidsetContextClassLoader(ClassLoader cl)Uses reflection to setThread#contextClassLoaderprimarily to sidestep a bug introduced in the JDK where if aSecurityManageris set,ForkJoinPoolusesInnocuousForkJoinWorkerThreadwhich overridessetContextClassLoader()to prevent it from being used by throwing an exception.static ObjectstructuralCall(Method structMethod, Object receiver, Object... args)static ObjectstructuralCallByProxy(Method structMethod, Object proxy, Object receiver, Object... args)static ReflectUtil.MethodRefstructuralMethod(Class target, Class structIface, String name, Class... params)static ReflectUtil.LiveMethodRefstructuralMethod(Object receiver, Class structIface, String name, Class... params)static Class<?>type(String fqn)Searches the class loader of this class for the specified name, if not found searches the current thread's context class loader.static Class<?>type(String fqn, boolean useCallChain)static Class<?>type(String fqn, ClassLoader cl)Searchesclfor the specified classfqn.static Class<?>type(String fqn, ClassLoader cl, boolean useCallChain)
-
-
-
Method Detail
-
type
public static Class<?> type(String fqn)
Searches the class loader of this class for the specified name, if not found searches the current thread's context class loader.- Parameters:
fqn- The qualified name of the type e.g.,"java.lang.String"or"java.lang.String[]"- Returns:
- The
Classcorresponding withfqnor null if not found
-
type
public static Class<?> type(String fqn, ClassLoader cl)
Searchesclfor the specified classfqn.- Parameters:
fqn- The qualified name of the type e.g.,"java.lang.String"cl- The class loader to search- Returns:
- The
Classcorresponding withfqnor null if not found
-
type
public static Class<?> type(String fqn, ClassLoader cl, boolean useCallChain)
-
method
public static ReflectUtil.LiveMethodRef method(Object receiver, String name, Class... params)
Get aReflectUtil.LiveMethodRefto the specified method. Typical use:method(str, "substring", int.class).invoke(2)
- Parameters:
receiver- The object to make the call onname- The name of the method to call or a '|' separated list of names, where the first found is usedparams- The types of the method's parameters- Returns:
- A reference to the specified method, throws
RuntimeExceptionif the method is not found. UseReflectUtil.WithNullto avoid the RuntimeException.
-
method
public static ReflectUtil.MethodRef method(String fqn, String name, Class... params)
Get aReflectUtil.MethodRefto the specified method. Typical use:method("java.time.LocalTime", "of", int.class, int.class).invokeStatic(5, 30)- Parameters:
fqn- The qualified name of the class containing the methodname- The name of the method or a '|' separated list of names, where the first found is usedparams- The types of the method's parameters- Returns:
- A reference to the specified method or null if not found
-
method
public static ReflectUtil.MethodRef method(Class<?> cls, String name, Class... params)
Get aReflectUtil.MethodRefto the specified method. Typical use:method(LocalTime.class, "of", int.class, int.class).invokeStatic(5, 30)
- Parameters:
cls- The class containing the methodname- The name of the method or a '|' separated list of names, where the first found is usedparams- The types of the method's parameters- Returns:
- A reference to the specified method or null if not found
-
methodFromName
public static ReflectUtil.MethodRef methodFromName(Class<?> cls, String name)
Get aReflectUtil.MethodRefto the specifiednamewithout regard to parameter types. If more than one method has thename, the first one encountered is used, in no particular order. This method should be used only when the named method is not overloaded. Typical use:methodByName(LocalTime.class, "isAfter").invoke(source, time)
- Parameters:
cls- The class containing the methodname- The name of the method or a '|' separated list of names, where the first found is used- Returns:
- A reference to the specified method or null if not found
-
lambdaMethod
public static ReflectUtil.MethodRef lambdaMethod(Class<?> lambdaClass)
Get aReflectUtil.MethodRefcorresponding with the functional interface implemented bylambdaClass.lambdaMethod(function.getClass()).invoke(function, args)
- Returns:
- A reference to the specified method or null if not found
-
invokeDefault
public static Object invokeDefault(Object receiver, Class<?> iface, String name, Class<?>[] params, Object... args)
This method behaves like the one below it, except this method ensures theifacedefault method is called even if thereceiveroverrides it. Essentially, this method is like calling Iface.super.method() from the receiver's perspective.
-
invokeDefault
public static Object invokeDefault(Object receiver, Method method, Object... args)
Invoke a default interface method. This is useful, for example, for a proxy implementation where there is no explicit implementation of the interface on which to invoke the default method.- Parameters:
receiver- The receiver of the call (the proxy instance in the case of a proxy impl).method- The default interface method to invoke onreceiver.args- The arguments tomethod.- Returns:
- The return value of
methodornullif the method has avoidreturn type.
-
field
public static ReflectUtil.LiveFieldRef field(Object receiver, String name)
Get aReflectUtil.LiveFieldRefto the specified field. Typical use:String name = field(foo, "name").get();
- Parameters:
receiver- The object having the fieldname- The name of the field or a '|' separated list of names, where the first found is used- Returns:
- A reference to the specified field, throws
RuntimeExceptionif the field is not found. UseReflectUtil.WithNullto avoid the RuntimeException.
-
field
public static ReflectUtil.FieldRef field(String fqn, String name)
Get aReflectUtil.FieldRefto the specified field. Typical use:field("java.time.LocalTime", "hour").get(time);- Parameters:
fqn- The qualified name of the class having the fieldname- The name of the field or a '|' separated list of names, where the first found is used- Returns:
- A reference to the specified field or null if not found
-
field
public static ReflectUtil.FieldRef field(Class<?> cls, String name)
Get aReflectUtil.FieldRefto the specified field. Typical use:field(LocalTime.class, "hour").get(time);
- Parameters:
cls- The class having the fieldname- The name of the field or a '|' separated list of names, where the first found is used- Returns:
- A reference to the specified field or null if not found
-
fields
public static List<ReflectUtil.LiveFieldRef> fields(Object receiver)
Visit declared fields of thereceiverclass. Stop iffunreturn false.
-
fields
public static List<ReflectUtil.LiveFieldRef> fields(Object receiver, Predicate<ReflectUtil.LiveFieldRef> filter)
-
constructor
public static ReflectUtil.ConstructorRef constructor(String fqn, Class<?>... params)
Get aReflectUtil.ConstructorRefto the specified constructor. Typical use:constructor("java.util.ArrayList", int.class).newInstance(32)- Parameters:
fqn- The qualified name of the class to constructparams- A list of parameter types for the constructor- Returns:
- A reference to the constructor or null if not found
-
constructor
public static ReflectUtil.ConstructorRef constructor(Class<?> cls, Class<?>... params)
Get aReflectUtil.ConstructorRefto the specified constructor. Typical use:constructor(ArrayList.class, int.class).newInstance(32)
- Parameters:
cls- The class to constructparams- A list of parameter types for the constructor- Returns:
- A reference to the constructor or null if not found
-
setAccessible
public static void setAccessible(Field f)
-
setAccessible
public static void setAccessible(Method m)
-
setAccessible
public static void setAccessible(Constructor c)
-
setAccessible
public static void setAccessible(Member m)
-
preloadClassIntoParentLoader
public static void preloadClassIntoParentLoader(String fqn, URI content, ClassLoader wouldBeLoader, ClassLoader parentLoader)
Force class with namefqnto be loaded byparentLoader. Facilitates the case where a class must be declared in a package defined in a parent class loader in order to subclass and use package-local features defined there.Note
fqn's natural class loader must have theparentLoaderin its chain of parent loaders. Also be certainfqnis not already loaded by its natural loader, otherwiseLinkageErrors will result.- Parameters:
fqn- The qualified name of the class to loadcontent- The location of the class resource. With Java 8 this can bewouldBeLoader.getResource(className). But with Java 9 and later the JPMS strictly prohibits a package from existing in two loaders, therefore the class file must be placed in a different package, perhaps prefixed with a suitably named root package, otherwise the VM will throw aLayerInstantiationExceptionwhen your application loads, before any of your code executes.wouldBeLoader- The class loader that would naturally loadfqn, must haveparentLoaderin its parent loader chainparentLoader- The class loader to load the class in, must be in the parent chain ofwouldBeLoader
-
structuralMethod
public static ReflectUtil.MethodRef structuralMethod(Class target, Class structIface, String name, Class... params)
-
structuralMethod
public static ReflectUtil.LiveMethodRef structuralMethod(Object receiver, Class structIface, String name, Class... params)
-
structuralCall
public static Object structuralCall(Method structMethod, Object receiver, Object... args)
-
structuralCallByProxy
public static Object structuralCallByProxy(Method structMethod, Object proxy, Object receiver, Object... args)
-
arePrimitiveTypesAssignable
public static boolean arePrimitiveTypesAssignable(Class toType, Class fromType)
-
setContextClassLoader
public static void setContextClassLoader(ClassLoader cl)
Uses reflection to setThread#contextClassLoaderprimarily to sidestep a bug introduced in the JDK where if aSecurityManageris set,ForkJoinPoolusesInnocuousForkJoinWorkerThreadwhich overridessetContextClassLoader()to prevent it from being used by throwing an exception. It is best to use reflection to set the contextClassLoader directly. Note, the JDK issue happens when launching the IntelliJrunIdetask for plugin dev.
-
-