
de.javagl.reflection.Methods Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of reflection Show documentation
Show all versions of reflection Show documentation
Reflection utility classes
/*
* www.javagl.de - Reflection
*
* Copyright 2013-2017 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import de.javagl.reflection.InvokableParser.InvokableInfo;
/**
* Utility methods related to methods.
*/
public class Methods
{
/**
* Parse the method from the given string. The given string must be
* the string that is obtained from a method by calling
* {@link Method#toString()} or {@link Method#toGenericString()}.
*
* @param fullMethodString The full method string
* @return The method
* @throws ReflectionException If the method can not be parsed
* for any reason. Either because the declaring class or any parameter
* class can not be found, or because the method is not found, or
* because the input string is otherwise invalid.
*/
public static Method parseMethodUnchecked(String fullMethodString)
{
InvokableInfo invokableInfo = InvokableParser.parse(fullMethodString);
// Fetch the fully qualified method name, which is of the form
// com.example.ClassName.methodName
// and extract the ClassName and methodName
String classAndMethodName = invokableInfo.getFullyQualifiedName();
int dotIndex = classAndMethodName.lastIndexOf('.');
if (dotIndex == -1)
{
throw new ReflectionException(
"No method in input string: " + fullMethodString);
}
String className = classAndMethodName.substring(0, dotIndex);
String methodName = classAndMethodName.substring(dotIndex+1);
// Try to find the declaring class
Class> declaringClass = Types.parseTypeUnchecked(className);
// Finally, try to find the method
Class> parameterTypes[] = invokableInfo.getParameterTypes();
Method result = getDeclaredMethodUnchecked(
declaringClass, methodName, parameterTypes);
return result;
}
//=========================================================================
// Single method
// general and declared
// fully qualified
// unchecked and optional
/**
* Delegates to {@link Class#getMethod(String, Class...)}.
*
* This call covers the following methods:
*
* - public methods
* - static and instance methods
* - including methods from supertypes
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @param methodName The method name
* @param parameterTypes The parameter types
* @return The method
* @throws ReflectionException if the the method could not be obtained
*/
public static Method getMethodUnchecked(
Class> type, String methodName, Class>... parameterTypes)
{
try
{
return type.getMethod(methodName, parameterTypes);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
catch (NoSuchMethodException e)
{
throw new ReflectionException(e);
}
}
/**
* Delegates to {@link Class#getMethod(String, Class...)}.
*
* This call covers the following methods:
*
* - public methods
* - static and instance methods
* - including methods from supertypes
*
*
* Returns null
if the underlying call did not succeed.
*
* @param type The type
* @param methodName The method name
* @param parameterTypes The parameter types
* @return The method, or null
if it could not be obtained
*/
public static Method getMethodOptional(
Class> type, String methodName, Class>... parameterTypes)
{
try
{
return type.getMethod(methodName, parameterTypes);
}
catch (SecurityException e)
{
return null;
}
catch (NoSuchMethodException e)
{
return null;
}
}
/**
* Delegates to {@link Class#getDeclaredMethod(String, Class...)}.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* - excluding methods from supertypes
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @param methodName The method name
* @param parameterTypes The parameter types
* @return The method
* @throws ReflectionException if the method could not be obtained
*/
public static Method getDeclaredMethodUnchecked(
Class> type, String methodName, Class>... parameterTypes)
{
try
{
return type.getDeclaredMethod(methodName, parameterTypes);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
catch (NoSuchMethodException e)
{
throw new ReflectionException(e);
}
}
/**
* Delegates to {@link Class#getDeclaredMethod(String, Class...)}.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* - excluding methods from supertypes
*
*
* Returns null
if the underlying call did not succeed.
*
* @param type The type
* @param methodName The method name
* @param parameterTypes The parameter types
* @return The method, or null
if it could not be obtained
*/
public static Method getDeclaredMethodOptional(
Class> type, String methodName, Class>... parameterTypes)
{
try
{
return type.getDeclaredMethod(methodName, parameterTypes);
}
catch (SecurityException e)
{
return null;
}
catch (NoSuchMethodException e)
{
return null;
}
}
//=========================================================================
// All methods
// general and declared
// unchecked and optional
/**
* Delegates to {@link Class#getMethods()}, and returns the result
* as an unmodifiable list.
*
* This call covers the following methods:
*
* - public methods
* - static and instance methods
* - including methods from supertypes
* -
* excluding the methods of supertypes that have been
* overridden by the given type
*
* -
* excluding the static methods of superinterfaces
*
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @return The methods
* @throws ReflectionException if the call did not succeed
*/
public static List getMethodsUnchecked(Class> type)
{
try
{
return Collections.unmodifiableList(
Arrays.asList(type.getMethods()));
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
}
/**
* Delegates to {@link Class#getMethods()}, and returns the result
* as an unmodifiable list.
*
* This call covers the following methods:
*
* - public methods
* - static and instance methods
* - including methods from supertypes
* -
* excluding the methods of supertypes that have been
* overridden by the given type
*
* -
* excluding the static methods of superinterfaces
*
*
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @return The method
*/
public static List getMethodsOptional(Class> type)
{
try
{
return Collections.unmodifiableList(
Arrays.asList(type.getMethods()));
}
catch (SecurityException e)
{
return Collections.emptyList();
}
}
/**
* Delegates to {@link Class#getDeclaredMethods()}, and returns the result
* as an unmodifiable list.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* - excluding methods from supertypes
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @return The method
* @throws ReflectionException if the call did not succeed
*/
public static List getDeclaredMethodsUnchecked(Class> type)
{
try
{
return Collections.unmodifiableList(
Arrays.asList(type.getDeclaredMethods()));
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
}
/**
* Delegates to {@link Class#getDeclaredMethods()}, and returns the result
* as an unmodifiable list.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* - excluding methods from supertypes
*
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @return The method
*/
public static List getDeclaredMethodsOptional(Class> type)
{
try
{
return Collections.unmodifiableList(
Arrays.asList(type.getDeclaredMethods()));
}
catch (SecurityException e)
{
return Collections.emptyList();
}
}
//=========================================================================
// All methods (deep search)
// general and declared
// unchecked and optional
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getMethods()} on the given type or any
* of its supertypes or its implemented interfaces.
*
* This call covers the following methods:
*
* - public methods
* - static and instance methods
* - including methods from supertypes
* -
* including the methods of supertypes that have been
* overridden by the given type
*
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @return The list of all methods
* @throws ReflectionException if the call did not succeed.
*/
public static List getAllMethodsUnchecked(
Class> type)
{
try
{
return getAllMethods(type);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getMethods()} on the given type or any
* of its supertypes or its implemented interfaces.
*
* This call covers the following methods:
*
* - public methods
* - static and instance methods
* - including methods from supertypes
* -
* including the methods of supertypes that have been
* overridden by the given type
*
*
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @return The list of all methods
*/
public static List getAllMethodsOptional(
Class> type)
{
try
{
return getAllMethods(type);
}
catch (SecurityException e)
{
return Collections.emptyList();
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getMethods()} on the given type or any
* of its supertypes or its implemented interfaces.
*
* @param type The type
* @return The list of inherited methods
* @throws SecurityException If the delegate call throws it
*/
private static List getAllMethods(Class> type)
{
Set methods = new LinkedHashSet();
methods.addAll(Arrays.asList(type.getMethods()));
Class> superclass = type.getSuperclass();
if (superclass != null)
{
methods.addAll(getAllMethods(superclass)); // Recursion done here!
}
if (type.isInterface())
{
methods.addAll(Arrays.asList(Object.class.getMethods()));
}
for (Class> i : type.getInterfaces())
{
methods.addAll(Arrays.asList(i.getMethods()));
}
return Collections.unmodifiableList(
new ArrayList(methods));
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getDeclaredMethods()} on the given type or any
* of its supertypes or its implemented interfaces.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* - including methods from supertypes
* -
* including the methods of supertypes that have been
* overridden by the given type
*
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @return The list of all declared methods
* @throws ReflectionException if the call did not succeed.
*/
public static List getAllDeclaredMethodsUnchecked(
Class> type)
{
try
{
return getAllDeclaredMethods(type);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getDeclaredMethods()} on the given type or any
* of its supertypes or its implemented interfaces.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* - including methods from supertypes
* -
* including the methods of supertypes that have been
* overridden by the given type
*
*
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @return The list of all declared methods
*/
public static List getAllDeclaredMethodsOptional(
Class> type)
{
try
{
return getAllDeclaredMethods(type);
}
catch (SecurityException e)
{
return Collections.emptyList();
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getDeclaredMethods()} on the given type or any
* of its supertypes or its implemented interfaces.
*
* @param type The type
* @return The list of inherited methods
* @throws SecurityException If the delegate call throws it
*/
private static List getAllDeclaredMethods(Class> type)
{
Set methods = new LinkedHashSet();
methods.addAll(Arrays.asList(type.getDeclaredMethods()));
Class> superclass = type.getSuperclass();
if (superclass != null)
{
methods.addAll(getAllDeclaredMethods(superclass)); // Recursion!
}
if (type.isInterface())
{
methods.addAll(Arrays.asList(Object.class.getDeclaredMethods()));
}
for (Class> i : type.getInterfaces())
{
methods.addAll(Arrays.asList(i.getDeclaredMethods()));
}
return Collections.unmodifiableList(
new ArrayList(methods));
}
//=========================================================================
// All own methods
// general and declared
// unchecked and optional
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getMethods()} on the given type, except for
* those that are inherited from any supertype or one of its implemented
* interfaces.
*
* This call covers the following methods:
*
* - public methods
* - instance methods
* -
* excluding methods from supertypes (even if they are
* overridden by the given type)
*
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @return The methods
* @throws ReflectionException if the call did not succeed.
*/
public static List getOwnMethodsUnchecked(Class> type)
{
try
{
return getOwnMethods(type);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getMethods()} on the given type, except for
* those that are inherited from any supertype or one of its implemented
* interfaces.
*
* This call covers the following methods:
*
* - public methods
* - instance methods
* -
* excluding methods from supertypes (even if they are
* overridden by the given type)
*
*
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @return The methods
*/
public static List getOwnMethodsOptional(Class> type)
{
try
{
return getOwnMethods(type);
}
catch (SecurityException e)
{
return Collections.emptyList();
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getMethods()} on the given type, except for
* those that are inherited from any supertype or one of its implemented
* interfaces.
*
* @param type The type
* @return The methods
* @throws SecurityException If the delegate call throws it
*/
private static List getOwnMethods(Class> type)
{
Set toRemove = new LinkedHashSet();
Class> superclass = type.getSuperclass();
if (superclass != null)
{
toRemove.addAll(Arrays.asList(superclass.getMethods()));
}
if (type.isInterface())
{
toRemove.addAll(Arrays.asList(Object.class.getMethods()));
}
for (Class> i : type.getInterfaces())
{
toRemove.addAll(Arrays.asList(i.getMethods()));
}
List result = new ArrayList();
for (Method method : type.getMethods())
{
if (!containsEquivalent(toRemove, method))
{
result.add(method);
}
}
return Collections.unmodifiableList(result);
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getDeclaredMethods()} on the given type,
* except for those that are inherited from any supertype or one of its
* implemented interfaces.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* -
* excluding methods from supertypes (even if they are
* overridden by the given type)
*
*
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @return The methods
* @throws ReflectionException if the call did not succeed.
*/
public static List getOwnDeclaredMethodsUnchecked(Class> type)
{
try
{
return getOwnDeclaredMethods(type);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getDeclaredMethods()} on the given type,
* except for those that are inherited from any supertype or one of its
* implemented interfaces.
*
* This call covers the following methods:
*
* -
* public, protected, default and
* private methods
*
* - static and instance methods
* -
* excluding methods from supertypes (even if they are
* overridden by the given type)
*
*
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @return The methods
*/
public static List getOwnDeclaredMethodsOptional(Class> type)
{
try
{
return getOwnDeclaredMethods(type);
}
catch (SecurityException e)
{
return Collections.emptyList();
}
}
/**
* Returns an unmodifiable list containing all methods of that are returned
* by a call to {@link Class#getDeclaredMethods()} on the given type, except
* for those that are inherited from any supertype or one of its implemented
* interfaces.
*
* @param type The type
* @return The methods
* @throws SecurityException If the delegate call throws it
*/
private static List getOwnDeclaredMethods(Class> type)
{
Set toRemove = new LinkedHashSet();
Class> superclass = type.getSuperclass();
if (superclass != null)
{
toRemove.addAll(Arrays.asList(superclass.getDeclaredMethods()));
}
if (type.isInterface())
{
toRemove.addAll(Arrays.asList(Object.class.getDeclaredMethods()));
}
for (Class> i : type.getInterfaces())
{
toRemove.addAll(Arrays.asList(i.getDeclaredMethods()));
}
List result = new ArrayList();
for (Method method : type.getDeclaredMethods())
{
if (!containsEquivalent(toRemove, method))
{
result.add(method);
}
}
return Collections.unmodifiableList(result);
}
/**
* Returns whether the given sequence contains a method that
* {@link #areEquivalent(Method, Method) is equivalent} to
* the given method.
*
* @param methods The methods
* @param method The method
* @return Whether one of the given methods is equivalent to the
* given method
*/
private static boolean containsEquivalent(
Iterable extends Method> methods, Method method)
{
for (Method other : methods)
{
if (areEquivalent(method, other))
{
return true;
}
}
return false;
}
/**
* Returns whether the given methods are equivalent. That is, whether
* they have equal names and parameter types.
*
* @param method0 The first method
* @param method1 The second method
* @return Whether the methods are equivalent
*/
private static boolean areEquivalent(Method method0, Method method1)
{
String name0 = method0.getName();
String name1 = method1.getName();
if (!name0.equals(name1))
{
return false;
}
Class> parameterTypes0[] = method0.getParameterTypes();
Class> parameterTypes1[] = method1.getParameterTypes();
return Arrays.equals(parameterTypes0, parameterTypes1);
}
//=========================================================================
/**
* Returns an unmodifiable list containing all methods of the given type
* that match the given predicates.
*
* This is equivalent to filtering the list of methods that is returned
* by {@link #getAllDeclaredMethodsOptional(Class)} with the given
* predicates.
*
* Returns an empty list if the underlying call did not succeed.
*
* @param type The type
* @param predicates The predicates
* @return The methods
*/
@SafeVarargs
public static List getAllOptional(
Class> type, Predicate super Method> ... predicates)
{
return Lists.filter(getAllDeclaredMethodsOptional(type), predicates);
}
/**
* Returns an unmodifiable list containing all methods of the given type
* that match the given predicates.
*
* This is equivalent to filtering the list of methods that is returned
* by {@link #getAllDeclaredMethodsUnchecked(Class)} with the given
* predicates.
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param type The type
* @param predicates The predicates
* @return The methods
* @throws ReflectionException if the call did not succeed
*/
@SafeVarargs
public static List getAllUnchecked(
Class> type, Predicate super Method> ... predicates)
{
return Lists.filter(getAllDeclaredMethodsUnchecked(type), predicates);
}
//=========================================================================
// Invocation
/**
* Delegates to {@link Method#invoke(Object, Object...)}.
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param method The method
* @param object The object
* @param arguments The arguments
* @return The method call result
* @throws ReflectionException if the call did not succeed
*/
public static Object invokeUnchecked(
Method method, Object object, Object ...arguments)
{
try
{
return method.invoke(object, arguments);
}
catch (IllegalArgumentException e)
{
throw new ReflectionException(e);
}
catch (IllegalAccessException e)
{
throw new ReflectionException(e);
}
catch (InvocationTargetException e)
{
throw new ReflectionException(e);
}
}
/**
* Delegates to {@link Method#invoke(Object, Object...)}.
*
* Any checked exception that may be thrown internally will silently
* be ignored, and null
will be returned in this case.
*
* @param method The method
* @param object The object
* @param arguments The arguments
* @return The method call result
*/
public static Object invokeOptional(
Method method, Object object, Object ...arguments)
{
try
{
return method.invoke(object, arguments);
}
catch (IllegalArgumentException e)
{
return null;
}
catch (IllegalAccessException e)
{
return null;
}
catch (InvocationTargetException e)
{
return null;
}
}
/**
* Delegates to {@link Method#invoke(Object, Object...)}.
*
* If the given method is not accessible, it will be set to be
* accessible and its accessibility status will be restored after
* the call.
*
* This call is wrapping all possible checked exceptions and
* SecurityExceptions into a {@link ReflectionException}
*
* @param method The method
* @param object The object
* @param arguments The arguments
* @return The method call result
* @throws ReflectionException if the call did not succeed
*/
public static Object invokeNonAccessibleUnchecked(
Method method, Object object, Object ...arguments)
{
boolean wasAccessible = method.isAccessible();
try
{
method.setAccessible(true);
Object result = method.invoke(object, arguments);
return result;
}
catch (IllegalArgumentException e)
{
throw new ReflectionException(e);
}
catch (IllegalAccessException e)
{
throw new ReflectionException(e);
}
catch (InvocationTargetException e)
{
throw new ReflectionException(e);
}
catch (SecurityException e)
{
throw new ReflectionException(e);
}
finally
{
method.setAccessible(wasAccessible);
}
}
/**
* Delegates to {@link Method#invoke(Object, Object...)}.
*
* If the given method is not accessible, it will be set to be
* accessible and its accessibility status will be restored after
* the call.
*
* Any checked exception that may be thrown internally will silently
* be ignored, and null
will be returned in this case.
*
* @param method The method
* @param object The object
* @param arguments The arguments
* @return The method call result
*/
public static Object invokeNonAccessibleOptional(
Method method, Object object, Object ...arguments)
{
boolean wasAccessible = method.isAccessible();
try
{
method.setAccessible(true);
Object result = method.invoke(object, arguments);
return result;
}
catch (IllegalArgumentException e)
{
return null;
}
catch (IllegalAccessException e)
{
return null;
}
catch (InvocationTargetException e)
{
return null;
}
catch (SecurityException e)
{
return null;
}
finally
{
method.setAccessible(wasAccessible);
}
}
/**
* Private constructor to prevent instantiation
*/
private Methods()
{
// Private constructor to prevent instantiation
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy