Java/Reflection/Method
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 An invocation handler that counts the number of calls for all methods in the target class.
- 2 Call a class method with 2 arguments
- 3 Call a member function to get the value
- 4 Call a method dynamically (Reflection)
- 5 Call a method of an object
- 6 Call a static method of a class with reflection
- 7 Call private method
- 8 Checks whether the specified class contains a method matching the specified name.
- 9 Class Reflection: show methods
- 10 Demonstrates dynamic usage of methods
- 11 Demonstrates how to get specific method information
- 12 Demonstration of various method invocation issues
- 13 Fetches all methods of all access types from the supplied class and super classes
- 14 Find a Method on the supplied class with the supplied name and no parameters
- 15 Find a Method on the supplied class with the supplied name and parameter types
- 16 Find method
- 17 Get a given method, and invoke it
- 18 Get all declared methods from a class
- 19 Get all methods including the inherited method. Using the getMethods(), we can only access public methods.
- 20 Get the class name in a static method
- 21 Get the current method name
- 22 Get the current method name With JDK1.5
- 23 Get the methods of a class object
- 24 Getting the Methods of a Class Object: By obtaining a list of all declared methods
- 25 Getting the Methods of a Class Object: By obtaining a list of all public methods, both declared and inherited.
- 26 Getting the Methods of a Class Object: By obtaining a particular Method object.
- 27 Invoke a method using Method class
- 28 Invoke method through Java Reflection API
- 29 Invokes a method, masking with a runtime exception all the exceptions.
- 30 Load a method on the fly
- 31 Make methods that have unspecified number of parameters:pass an array of Objects
- 32 Method modifiers: isSynthetic(), m.isVarArgs(), m.isBridge()
- 33 Method Reflection
- 34 Object Reflection: invoke methods
- 35 Returns method with the specified name
- 36 Show loading a class and finding and calling its Main method
- 37 Sorts methods according to their name, number of parameters, and parameter types.
- 38 The next example calls a class method with 2 arguments:
- 39 To get the calling method
- 40 Using reflection to show all the methods of a class,
An invocation handler that counts the number of calls for all methods in the target class.
/*
* file: SomeClassFactory.java
* package: oreilly.hcj.proxies
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* An invocation handler that counts the number of calls for all methods in the
* target class.
*
* @author
* @version $Revision: 1.2 $
*/
public class DemoDynamicProxy {
/**
* Run the demonstration.
*
* @param args Command Line Arguments (ignored).
*/
public static final void main(final String[] args) {
SomeClass proxy = SomeClassFactory.getDynamicSomeClassProxy();
proxy.someMethod();
proxy.someOtherMethod("Our Proxy works!");
InvocationHandler handler = Proxy.getInvocationHandler(proxy);
if (handler instanceof MethodCountingHandler) {
System.out.println(((MethodCountingHandler)handler).getInvocationCount());
}
}
}
/* ########## End of File ########## */
Call a class method with 2 arguments
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
Class c = Class.forName("MyClass");
Method m = c.getDeclaredMethod("say", new Class[] { String.class, String.class });
Object i = c.newInstance();
Object r = m.invoke(i, new Object[] { "Hello","World" });
}
}
class MyClass {
public void say(String s1, String s2) {
System.out.println(s1 + " " + s2);
}
}
Call a member function to get the value
// $Id: ReflectionHelper.java 16271 2009-04-07 20:20:12Z hardy.ferentschik $
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Some reflection utility methods.
*
* @author Hardy Ferentschik
*/
public class ReflectionHelper {
public static Object getValue(Member member, Object object) {
Object value = null;
if ( member instanceof Method ) {
Method method = ( Method ) member;
try {
value = method.invoke( object );
}
catch ( IllegalAccessException e ) {
throw new RuntimeException( "Unable to access " + method.getName(), e );
}
catch ( InvocationTargetException e ) {
throw new RuntimeException( "Unable to access " + method.getName(), e );
}
}
else if ( member instanceof Field ) {
Field field = ( Field ) member;
try {
value = field.get( object );
}
catch ( IllegalAccessException e ) {
throw new RuntimeException( "Unable to access " + field.getName(), e );
}
}
return value;
}
}
Call a method dynamically (Reflection)
import java.lang.reflect.Method;
public class Main {
public static void main(String s[]) throws Exception {
String aClass = "Class1";
String aMethod = "class1Method1";
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(aClass);
Object iClass = thisClass.newInstance();
Method thisMethod = thisClass.getDeclaredMethod(aMethod, params);
System.out.println(thisMethod.invoke(iClass, paramsObj).toString());
}
}
class Class1 {
public String class1Method1() {
return "Method1";
}
public String class1Method2() {
return "Method2";
}
}
Call a method of an object
import java.lang.reflect.Method;
/**
* Handy reflection routines.
*/
public abstract class Reflect {
/**
* Call a method of an object.
*/
public static Object callMethod (Object obj,
String methodName,
Class[] signature,
Object[] args)
throws Exception {
Class cls = obj.getClass ();
Method method = cls.getMethod (methodName, signature);
return method.invoke (obj, args);
}
}
Call a static method of a class with reflection
import java.lang.reflect.Method;
/**
* Handy reflection routines.
*/
public abstract class Reflect {
/**
* Call a static method of a class.
*/
public static Object callStaticMethod (String className,
String methodName,
Class[] signature,
Object[] args)
throws Exception {
Class cls = Class.forName (className);
Method method = cls.getMethod (methodName, signature);
return method.invoke (cls, args);
}
}
Call private method
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class AnotherClass {
private void m() {
}
}
public class MethodTroubleAgain {
public static void main(String... args) {
AnotherClass ac = new AnotherClass();
try {
Class<?> c = ac.getClass();
Method m = c.getDeclaredMethod("m");
// m.setAccessible(true); // solution
Object o = m.invoke(ac); // IllegalAccessException
// production code should handle these exceptions more gracefully
} catch (NoSuchMethodException x) {
x.printStackTrace();
} catch (InvocationTargetException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
}
}
}
Checks whether the specified class contains a method matching the specified name.
// $Id: ReflectionHelper.java 16271 2009-04-07 20:20:12Z hardy.ferentschik $
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Some reflection utility methods.
*
* @author Hardy Ferentschik
*/
public class ReflectionHelper {
/**
* Checks whether the specified class contains a method matching the specified name.
*
* @param clazz The class to check.
* @param methodName The method name.
*
* @return Returns <code>true</code> if the cass contains a property for the specified name, <code>
* false</code> otherwise.
*/
public static boolean containsMethod(Class<?> clazz, String methodName) {
try {
clazz.getMethod( "get" + methodName.substring( 0, 1 ).toUpperCase() + methodName.substring( 1 ) );
return true;
}
catch ( NoSuchMethodException e ) {
return false;
}
}
}
Class Reflection: show methods
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies. Please refer to
* the file "copyright.html" for further important copyright and licensing
* information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES.
*/
import java.awt.Polygon;
import java.lang.reflect.Method;
public class SampleMethod {
public static void main(String[] args) {
Polygon p = new Polygon();
showMethods(p);
}
static void showMethods(Object o) {
Class c = o.getClass();
Method[] theMethods = c.getMethods();
for (int i = 0; i < theMethods.length; i++) {
String methodString = theMethods[i].getName();
System.out.println("Name: " + methodString);
String returnString = theMethods[i].getReturnType().getName();
System.out.println(" Return Type: " + returnString);
Class[] parameterTypes = theMethods[i].getParameterTypes();
System.out.print(" Parameter Types:");
for (int k = 0; k < parameterTypes.length; k++) {
String parameterString = parameterTypes[k].getName();
System.out.print(" " + parameterString);
}
System.out.println();
}
}
}
Demonstrates dynamic usage of methods
/*
* file: MethodUsageDemo.java
* package: oreilly.hcj.reflection
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */
//package oreilly.hcj.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.util.Locale;
/**
* Demonstrates dynamic usage of methods.
*
* @author
* @version $Revision: 1.3 $
*/
public class MethodUsageDemo {
/** Date formatter to be used. */
static final DateFormat DATE_FORMATTER = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
/**
* Ouput the values of the "get" methods.
*
* @param obj
* The object to output.
*
* @throws InvocationTargetException
* If an error occurs in calling the get methods.
* @throws IllegalAccessException
* If the security manager rejects access.
*/
public static final void outputValues(final Object obj) throws InvocationTargetException,
IllegalAccessException {
final String PREFIX = "get"; //$NON-NLS-1$
System.out.println("--- Accessing Get Methods ---");
Method[] meths = obj.getClass().getMethods();
for (int idx = 0; idx < meths.length; idx++) {
if (meths[idx].getName().startsWith(PREFIX)) {
if (meths[idx].getParameterTypes().length == 0) {
System.out.print(meths[idx].getName() + " = "); //$NON-NLS-1$
System.out.println(meths[idx].invoke(obj, null));
}
}
}
}
/**
* Main method.
*
* @param args
* Command line arguments.
*
* @throws RuntimeException
* If an unforseen error occurs.
*/
public static void main(final String[] args) {
try {
// person.setBirthDate(DATE_FORMATTER.parse("01/12/1971"));
// Output the object.
outputValues(new String());
} catch (final Exception ex) {
throw new RuntimeException(ex);
}
}
}
/* ########## End of File ########## */
Demonstrates how to get specific method information
import java.lang.reflect.Method;
/**
* Demonstrates how to get specific method information.
*
* @author
* @version $Revision: 1.3 $
*/
public class SpecificMethodInfoDemo {
public static void main(final String[] args) {
final Method byteValueMeth;
final Method waitMeth;
final Method waitDetailMeth;
try {
byteValueMeth = Number.class.getMethod("byteValue", null);
waitMeth = Number.class.getMethod("wait", new Class[] {});
waitDetailMeth = Number.class.getMethod("wait", new Class[] { long.class, int.class });
} catch (final NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
System.out.println("byteValueMeth = " + byteValueMeth.toString());
System.out.println("waitMeth = " + waitMeth.toString());
System.out.println("waitDetailMeth = " + waitDetailMeth.toString());
}
}
Demonstration of various method invocation issues
/*
* file: VariousMethodDemos.java
* package: oreilly.hcj.reflection
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */
import java.lang.reflect.Method;
/**
* Demonstration of various method invocation issues.
*
* @author
* @version $Revision$
*/
public class VariousMethodDemos {
/**
* Run the demo.
*
* @param args
* Command line arguments (ignored).
*/
public static void main(final String[] args) {
try {
final Class[] ARG_TYPES = new Class[] { String.class };
Object result = null;
Method meth = Integer.class.getMethod("parseInt", ARG_TYPES);
result = meth.invoke(null, new Object[] { new String("44") });
System.out.println(result);
result = meth.invoke(null, new Object[] { new String("Jonny") });
System.out.println(result);
} catch (final Exception ex) {
ex.printStackTrace();
}
}
}
/* ########## End of File ########## */
Fetches all methods of all access types from the supplied class and super classes
import java.util.Map;
import java.util.HashMap;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Queue;
import java.util.LinkedList;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import static java.lang.reflect.Modifier.isPublic;
import java.beans.PropertyDescriptor;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.IntrospectionException;
/**
* Common utilty methods that are useful when working with reflection.
*
* @author Tim Fennell
*/
public class ReflectUtil {
/** A cache of property descriptors by class and property name */
private static Map<Class<?>, Map<String, PropertyDescriptor>> propertyDescriptors =
new ConcurrentHashMap<Class<?>, Map<String, PropertyDescriptor>>();
/** Static helper class, shouldn"t be constructed. */
private ReflectUtil() {}
/**
* Holds a map of commonly used interface types (mostly collections) to a class that
* implements the interface and will, by default, be instantiated when an instance
* of the interface is needed.
*/
protected static final Map<Class<?>,Class<?>> interfaceImplementations = new HashMap<Class<?>,Class<?>>();
/**
* Holds a map of primitive type to the default value for that primitive type. Isn"t it
* odd that there"s no way to get this programmatically from the Class objects?
*/
protected static final Map<Class<?>,Object> primitiveDefaults = new HashMap<Class<?>,Object>();
static {
interfaceImplementations.put(Collection.class, ArrayList.class);
interfaceImplementations.put(List.class, ArrayList.class);
interfaceImplementations.put(Set.class, HashSet.class);
interfaceImplementations.put(SortedSet.class, TreeSet.class);
interfaceImplementations.put(Queue.class, LinkedList.class);
interfaceImplementations.put(Map.class, HashMap.class);
interfaceImplementations.put(SortedMap.class, TreeMap.class);
primitiveDefaults.put(Boolean.TYPE, false);
primitiveDefaults.put(Character.TYPE, "\0");
primitiveDefaults.put(Byte.TYPE, new Byte("0"));
primitiveDefaults.put(Short.TYPE, new Short("0"));
primitiveDefaults.put(Integer.TYPE, new Integer(0));
primitiveDefaults.put(Long.TYPE, new Long(0l));
primitiveDefaults.put(Float.TYPE, new Float(0f));
primitiveDefaults.put(Double.TYPE, new Double(0.0));
}
/**
* The set of method that annotation classes inherit, and should be avoided when
* toString()ing an annotation class.
*/
private static final Set<String> INHERITED_ANNOTATION_METHODS =
new HashSet(Arrays.asList("toString", "equals", "hashCode", "annotationType"));
/**
* Looks up the default implementing type for the supplied interface. This is done
* based on a static map of known common interface types and implementing classes.
*
* @param iface an interface for which an implementing class is needed
* @return a Class object representing the implementing type, or null if one is
* not found
*/
public static Class<?> getImplementingClass(Class<?> iface) {
return interfaceImplementations.get(iface);
}
/**
* Attempts to determine an implementing class for the interface provided and instantiate
* it using a default constructor.
*
* @param interfaceType an interface (or abstract class) to make an instance of
* @return an instance of the interface type supplied
* @throws InstantiationException if no implementation type has been configured
* @throws IllegalAccessException if thrown by the JVM during class instantiation
*/
@SuppressWarnings("unchecked")
public static <T> T getInterfaceInstance(Class<T> interfaceType)
throws InstantiationException, IllegalAccessException {
Class impl = getImplementingClass(interfaceType);
if (impl == null) {
throw new InstantiationException(
"Stripes needed to instantiate a property who"s declared type as an " +
"interface (which obviously cannot be instantiated. The interface is not " +
"one that Stripes is aware of, so no implementing class was known. The " +
"interface type was: "" + interfaceType.getName() + "". To fix this " +
"you"ll need to do one of three things. 1) Change the getter/setter methods " +
"to use a concrete type so that Stripes can instantiate it. 2) in the bean"s " +
"setContext() method pre-instantiate the property so Stripes doesn"t have to. " +
"3) Bug the Stripes author ;) If the interface is a JDK type it can easily be " +
"fixed. If not, if enough people ask, a generic way to handle the problem " +
"might get implemented.");
}
else {
return (T) impl.newInstance();
}
}
/**
* Utility method used to load a class. Any time that Stripes needs to load of find a
* class by name it uses this method. As a result any time the classloading strategy
* needs to change it can be done in one place! Currently uses
* {@code Thread.currentThread().getContextClassLoader().loadClass(String)}.
*
* @param name the fully qualified (binary) name of the class to find or load
* @return the Class object representing the class
* @throws ClassNotFoundException if the class cannot be loaded
*/
@SuppressWarnings("unchecked") // this allows us to assign without casting
public static Class findClass(String name) throws ClassNotFoundException {
return Thread.currentThread().getContextClassLoader().loadClass(name);
}
/**
* <p>A better (more concise) toString method for annotation types that yields a String
* that should look more like the actual usage of the annotation in a class. The String produced
* is similar to that produced by calling toString() on the annotation directly, with the
* following differences:</p>
*
* <ul>
* <li>Uses the classes simple name instead of it"s fully qualified name.</li>
* <li>Only outputs attributes that are set to non-default values.</li>
*
* <p>If, for some unforseen reason, an exception is thrown within this method it will be
* caught and the return value will be {@code ann.toString()}.
*
* @param ann the annotation to convert to a human readable String
* @return a human readable String form of the annotation and it"s attributes
*/
public static String toString(Annotation ann) {
try {
Class<? extends Annotation> type = ann.annotationType();
StringBuilder builder = new StringBuilder(128);
builder.append("@");
builder.append(type.getSimpleName());
boolean appendedAnyParameters = false;
Method[] methods = type.getMethods();
for (Method method : methods) {
if (!INHERITED_ANNOTATION_METHODS.contains(method.getName())) {
Object defaultValue = method.getDefaultValue();
Object actualValue = method.invoke(ann);
// If we have arrays, they have to be treated a little differently
Object[] defaultArray = null, actualArray = null;
if ( Object[].class.isAssignableFrom(method.getReturnType()) ) {
defaultArray = (Object[]) defaultValue;
actualArray = (Object[]) actualValue;
}
// Only print an attribute if it isn"t set to the default value
if ( (defaultArray != null && !Arrays.equals(defaultArray, actualArray)) ||
(defaultArray == null && !actualValue.equals(defaultValue)) ) {
if (appendedAnyParameters) {
builder.append(", ");
}
else {
builder.append("(");
}
builder.append(method.getName());
builder.append("=");
if (actualArray != null) {
builder.append( Arrays.toString(actualArray) );
}
else {
builder.append(actualValue);
}
appendedAnyParameters = true;
}
}
}
if (appendedAnyParameters) {
builder.append(")");
}
return builder.toString();
}
catch (Exception e) {
return ann.toString();
}
}
/**
* Fetches all methods of all access types from the supplied class and super
* classes. Methods that have been overridden in the inheritance hierarchy are
* only returned once, using the instance lowest down the hierarchy.
*
* @param clazz the class to inspect
* @return a collection of methods
*/
public static Collection<Method> getMethods(Class<?> clazz) {
Collection<Method> found = new ArrayList<Method>();
while (clazz != null) {
for (Method m1 : clazz.getDeclaredMethods()) {
boolean overridden = false;
for (Method m2 : found) {
if ( m2.getName().equals(m1.getName()) &&
Arrays.deepEquals(m1.getParameterTypes(), m2.getParameterTypes())) {
overridden = true;
break;
}
}
if (!overridden) found.add(m1);
}
clazz = clazz.getSuperclass();
}
return found;
}
/**
* Fetches all fields of all access types from the supplied class and super
* classes. Fieldss that have been overridden in the inheritance hierarchy are
* only returned once, using the instance lowest down the hierarchy.
*
* @param clazz the class to inspect
* @return a collection of fields
*/
public static Collection<Field> getFields(Class<?> clazz) {
Map<String,Field> fields = new HashMap<String, Field>();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
if ( !fields.containsKey(field.getName()) ) {
fields.put(field.getName(), field);
}
}
clazz = clazz.getSuperclass();
}
return fields.values();
}
/**
* Fetches the property descriptor for the named property of the supplied class. To
* speed things up a cache is maintained of propertyName to PropertyDescriptor for
* each class used with this method. If there is no property with the specified name,
* returns null.
*
* @param clazz the class who"s properties to examine
* @param property the String name of the property to look for
* @return the PropertyDescriptor or null if none is found with a matching name
*/
public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String property) {
Map<String,PropertyDescriptor> pds = propertyDescriptors.get(clazz);
if (pds == null) {
try {
BeanInfo info = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
pds = new HashMap<String, PropertyDescriptor>();
for (PropertyDescriptor descriptor : descriptors) {
pds.put(descriptor.getName(), descriptor);
}
propertyDescriptors.put(clazz, pds);
}
catch (IntrospectionException ie) {
throw new RuntimeException("Could not examine class "" + clazz.getName() +
"" using Introspector.getBeanInfo() to determine property information.", ie);
}
}
return pds.get(property);
}
/**
* <p>Attempts to find an accessible version of the method passed in, where accessible
* is defined as the method itself being public and the declaring class being public.
* Mostly useful as a workaround to the situation when
* {@link PropertyDescriptor#getReadMethod()} and/or
* {@link java.beans.PropertyDescriptor#getWriteMethod()} returns methods that are not
* accessible (usually due to public implementations of interface methods in private
* classes).</p>
*
* <p>Checks the method passed in and if it already meets these criteria it is returned
* immediately. In general this leads to very little performance overhead</p>
*
* <p>If the method does not meet the criteria then the class" interfaces are scanned
* for a matching method. If one is not found, then the class" superclass hierarchy
* is searched. Finally, if no matching method can be found the original method is
* returned.</p>
*
* @param m a method that may or may not be accessible
* @return either an accessible version of the same method, or the method passed in if
* an accessible version cannot be found
*/
public static Method findAccessibleMethod(final Method m) {
// If the passed in method is accessible, then just give it back.
if (isPublic(m.getModifiers()) && isPublic(m.getDeclaringClass().getModifiers())) return m;
if (m.isAccessible()) return m;
final Class<?> clazz = m.getDeclaringClass();
final String name = m.getName();
final Class<?>[] ptypes = m.getParameterTypes();
// Else, loop through the interfaces for the declaring class, looking for a
// public version of the method that we can call
for (Class<?> iface : clazz.getInterfaces()) {
try {
Method m2 = iface.getMethod(name, ptypes);
if (m2.isAccessible()) return m2;
if (isPublic(iface.getModifiers()) && isPublic(m2.getModifiers())) return m2;
}
catch (NoSuchMethodException nsme) { /* Not Unexpected. */ }
}
// Else loop through the superclasses looking for a public method
Class<?> c = clazz.getSuperclass();
while (c != null) {
try {
Method m2 = c.getMethod(name, ptypes);
if (m2.isAccessible()) return m2;
if (isPublic(c.getModifiers()) && isPublic(m2.getModifiers())) return m2;
}
catch (NoSuchMethodException nsme) { /* Not Unexpected. */ }
c = c.getSuperclass();
}
// If we haven"t found anything at this point, just give up!
return m;
}
/**
* Looks for an instance (i.e. non-static) public field with the matching name and
* returns it if one exists. If no such field exists, returns null.
*
* @param clazz the clazz who"s fields to examine
* @param property the name of the property/field to look for
* @return the Field object or null if no matching field exists
*/
public static Field getField(Class<?> clazz, String property) {
try {
Field field = clazz.getField(property);
return !Modifier.isStatic(field.getModifiers()) ? field : null;
}
catch (NoSuchFieldException nsfe) {
return null;
}
}
/**
* Returns an appropriate default value for the class supplied. Mirrors the defaults used
* when the JVM initializes instance variables.
*
* @param clazz the class for which to find the default value
* @return null for non-primitive types and an appropriate wrapper instance for primitives
*/
public static Object getDefaultValue(Class<?> clazz) {
if (clazz.isPrimitive()) {
return primitiveDefaults.get(clazz);
}
else {
return null;
}
}
/**
* Returns a set of all interfaces implemented by class supplied. This includes all
* interfaces directly implemented by this class as well as those implemented by
* superclasses or interface superclasses.
*
* @param clazz
* @return all interfaces implemented by this class
*/
public static Set<Class<?>> getImplementedInterfaces(Class<?> clazz)
{
Set<Class<?>> interfaces = new HashSet<Class<?>>();
if (clazz.isInterface())
interfaces.add(clazz);
while (clazz != null) {
for (Class<?> iface : clazz.getInterfaces())
interfaces.addAll(getImplementedInterfaces(iface));
clazz = clazz.getSuperclass();
}
return interfaces;
}
/**
* Returns an array of Type objects representing the actual type arguments
* to targetType used by clazz.
*
* @param clazz the implementing class (or subclass)
* @param targetType the implemented generic class or interface
* @return an array of Type objects or null
*/
public static Type[] getActualTypeArguments(Class<?> clazz, Class<?> targetType) {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(clazz);
if (targetType.isInterface())
classes.addAll(getImplementedInterfaces(clazz));
Class<?> superClass = clazz.getSuperclass();
while (superClass != null) {
classes.add(superClass);
superClass = superClass.getSuperclass();
}
for (Class<?> search : classes) {
for (Type type : (targetType.isInterface() ? search.getGenericInterfaces()
: new Type[] { search.getGenericSuperclass() })) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
if (targetType.equals(parameterizedType.getRawType()))
return parameterizedType.getActualTypeArguments();
}
}
}
return null;
}
}
Find a Method on the supplied class with the supplied name and no parameters
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Simple utility class for working with the reflection API and handling
* reflection exceptions.
*
* <p>Only intended for internal use.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @author Rod Johnson
* @author Costin Leau
* @since 1.2.2
*/
public abstract class ReflectionUtils {
/**
* Attempt to find a {@link Method} on the supplied class with the supplied name
* and no parameters. Searches all superclasses up to <code>Object</code>.
* <p>Returns <code>null</code> if no {@link Method} can be found.
* @param clazz the class to introspect
* @param name the name of the method
* @return the Method object, or <code>null</code> if none found
*/
public static Method findMethod(Class clazz, String name) {
return findMethod(clazz, name, new Class[0]);
}
/**
* Attempt to find a {@link Method} on the supplied class with the supplied name
* and parameter types. Searches all superclasses up to <code>Object</code>.
* <p>Returns <code>null</code> if no {@link Method} can be found.
* @param clazz the class to introspect
* @param name the name of the method
* @param paramTypes the parameter types of the method
* @return the Method object, or <code>null</code> if none found
*/
public static Method findMethod(Class clazz, String name, Class[] paramTypes) {
Class searchType = clazz;
while (!Object.class.equals(searchType) && searchType != null) {
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (name.equals(method.getName()) && Arrays.equals(paramTypes, method.getParameterTypes())) {
return method;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
}
Find a Method on the supplied class with the supplied name and parameter types
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Simple utility class for working with the reflection API and handling
* reflection exceptions.
*
* <p>Only intended for internal use.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @author Rod Johnson
* @author Costin Leau
* @since 1.2.2
*/
public abstract class ReflectionUtils {
/**
* Attempt to find a {@link Method} on the supplied class with the supplied name
* and no parameters. Searches all superclasses up to <code>Object</code>.
* <p>Returns <code>null</code> if no {@link Method} can be found.
* @param clazz the class to introspect
* @param name the name of the method
* @return the Method object, or <code>null</code> if none found
*/
public static Method findMethod(Class clazz, String name) {
return findMethod(clazz, name, new Class[0]);
}
/**
* Attempt to find a {@link Method} on the supplied class with the supplied name
* and parameter types. Searches all superclasses up to <code>Object</code>.
* <p>Returns <code>null</code> if no {@link Method} can be found.
* @param clazz the class to introspect
* @param name the name of the method
* @param paramTypes the parameter types of the method
* @return the Method object, or <code>null</code> if none found
*/
public static Method findMethod(Class clazz, String name, Class[] paramTypes) {
Class searchType = clazz;
while (!Object.class.equals(searchType) && searchType != null) {
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (name.equals(method.getName()) && Arrays.equals(paramTypes, method.getParameterTypes())) {
return method;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
}
Find method
//
//$Id: IntrospectionUtil.java 1540 2007-01-19 12:24:10Z janb $
//Copyright 2006 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
public class IntrospectionUtil {
public static Method findMethod(Class clazz, String methodName, Class[] args,
boolean checkInheritance, boolean strictArgs) throws NoSuchMethodException {
if (clazz == null)
throw new NoSuchMethodException("No class");
if (methodName == null || methodName.trim().equals(""))
throw new NoSuchMethodException("No method name");
Method method = null;
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length && method == null; i++) {
if (methods[i].getName().equals(methodName)
&& checkParams(methods[i].getParameterTypes(), (args == null ? new Class[] {} : args),
strictArgs)) {
method = methods[i];
}
}
if (method != null) {
return method;
} else if (checkInheritance)
return findInheritedMethod(clazz.getPackage(), clazz.getSuperclass(), methodName, args,
strictArgs);
else
throw new NoSuchMethodException("No such method " + methodName + " on class "
+ clazz.getName());
}
public static Field findField(Class clazz, String targetName, Class targetType,
boolean checkInheritance, boolean strictType) throws NoSuchFieldException {
if (clazz == null)
throw new NoSuchFieldException("No class");
if (targetName == null)
throw new NoSuchFieldException("No field name");
try {
Field field = clazz.getDeclaredField(targetName);
if (strictType) {
if (field.getType().equals(targetType))
return field;
} else {
if (field.getType().isAssignableFrom(targetType))
return field;
}
if (checkInheritance) {
return findInheritedField(clazz.getPackage(), clazz.getSuperclass(), targetName,
targetType, strictType);
} else
throw new NoSuchFieldException("No field with name " + targetName + " in class "
+ clazz.getName() + " of type " + targetType);
} catch (NoSuchFieldException e) {
return findInheritedField(clazz.getPackage(), clazz.getSuperclass(), targetName, targetType,
strictType);
}
}
public static boolean isInheritable(Package pack, Member member) {
if (pack == null)
return false;
if (member == null)
return false;
int modifiers = member.getModifiers();
if (Modifier.isPublic(modifiers))
return true;
if (Modifier.isProtected(modifiers))
return true;
if (!Modifier.isPrivate(modifiers) && pack.equals(member.getDeclaringClass().getPackage()))
return true;
return false;
}
public static boolean checkParams(Class[] formalParams, Class[] actualParams, boolean strict) {
if (formalParams == null && actualParams == null)
return true;
if (formalParams == null && actualParams != null)
return false;
if (formalParams != null && actualParams == null)
return false;
if (formalParams.length != actualParams.length)
return false;
if (formalParams.length == 0)
return true;
int j = 0;
if (strict) {
while (j < formalParams.length && formalParams[j].equals(actualParams[j]))
j++;
} else {
while ((j < formalParams.length) && (formalParams[j].isAssignableFrom(actualParams[j]))) {
j++;
}
}
if (j != formalParams.length) {
return false;
}
return true;
}
public static boolean isSameSignature(Method methodA, Method methodB) {
if (methodA == null)
return false;
if (methodB == null)
return false;
List parameterTypesA = Arrays.asList(methodA.getParameterTypes());
List parameterTypesB = Arrays.asList(methodB.getParameterTypes());
if (methodA.getName().equals(methodB.getName()) && parameterTypesA.containsAll(parameterTypesB))
return true;
return false;
}
public static boolean isTypeCompatible(Class formalType, Class actualType, boolean strict) {
if (formalType == null && actualType != null)
return false;
if (formalType != null && actualType == null)
return false;
if (formalType == null && actualType == null)
return true;
if (strict)
return formalType.equals(actualType);
else
return formalType.isAssignableFrom(actualType);
}
public static boolean containsSameMethodSignature(Method method, Class c, boolean checkPackage) {
if (checkPackage) {
if (!c.getPackage().equals(method.getDeclaringClass().getPackage()))
return false;
}
boolean samesig = false;
Method[] methods = c.getDeclaredMethods();
for (int i = 0; i < methods.length && !samesig; i++) {
if (IntrospectionUtil.isSameSignature(method, methods[i]))
samesig = true;
}
return samesig;
}
public static boolean containsSameFieldName(Field field, Class c, boolean checkPackage) {
if (checkPackage) {
if (!c.getPackage().equals(field.getDeclaringClass().getPackage()))
return false;
}
boolean sameName = false;
Field[] fields = c.getDeclaredFields();
for (int i = 0; i < fields.length && !sameName; i++) {
if (fields[i].getName().equals(field.getName()))
sameName = true;
}
return sameName;
}
protected static Method findInheritedMethod(Package pack, Class clazz, String methodName,
Class[] args, boolean strictArgs) throws NoSuchMethodException {
if (clazz == null)
throw new NoSuchMethodException("No class");
if (methodName == null)
throw new NoSuchMethodException("No method name");
Method method = null;
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length && method == null; i++) {
if (methods[i].getName().equals(methodName) && isInheritable(pack, methods[i])
&& checkParams(methods[i].getParameterTypes(), args, strictArgs))
method = methods[i];
}
if (method != null) {
return method;
} else
return findInheritedMethod(clazz.getPackage(), clazz.getSuperclass(), methodName, args,
strictArgs);
}
protected static Field findInheritedField(Package pack, Class clazz, String fieldName,
Class fieldType, boolean strictType) throws NoSuchFieldException {
if (clazz == null)
throw new NoSuchFieldException("No class");
if (fieldName == null)
throw new NoSuchFieldException("No field name");
try {
Field field = clazz.getDeclaredField(fieldName);
if (isInheritable(pack, field) && isTypeCompatible(fieldType, field.getType(), strictType))
return field;
else
return findInheritedField(clazz.getPackage(), clazz.getSuperclass(), fieldName, fieldType,
strictType);
} catch (NoSuchFieldException e) {
return findInheritedField(clazz.getPackage(), clazz.getSuperclass(), fieldName, fieldType,
strictType);
}
}
}
Get a given method, and invoke it
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.lang.reflect.Method;
/**
* This class is just here to give us something to work on, with a println()
* call that will prove we got here.
*/
class X {
public void work(String s) {
System.out.println("Working on \"" + s + "\"");
}
}
/**
* Get a given method, and invoke it.
*
* @author Ian F. Darwin, http://www.darwinsys.ru/
* @version $Id: GetMethod.java,v 1.3 2004/02/09 03:33:51 ian Exp $
*/
public class GetMethod {
public static void main(String[] argv) {
try {
Class clX = X.class; // or Class.forName("X");
// To find a method we need the array of matching Class types.
Class[] argTypes = { String.class };
// Now find a Method object for the given method.
Method worker = clX.getMethod("work", argTypes);
// To INVOKE the method, we need its actual arguments, as an array.
Object[] theData = { "Chocolate Chips" };
// The obvious last step: invoke the method.
worker.invoke(new X(), theData);
} catch (Exception e) {
System.err.println("Invoke() failed: " + e);
}
}
}
Get all declared methods from a class
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main{
public static void main(String args[]) throws Exception {
Class c = Class.forName("MyClass");
System.out.println("\nMethods:");
Method methods[] = c.getDeclaredMethods();
for (Method meth : methods)
System.out.println(" " + meth);
}
}
class MyClass {
private int count;
MyClass(int c) {
count = c;
}
MyClass() {
count = 0;
}
void setCount(int c) {
count = c;
}
int getCount() {
return count;
}
void showcount() {
System.out.println("count is " + count);
}
}
Get all methods including the inherited method. Using the getMethods(), we can only access public methods.
import java.lang.reflect.Method;
class GetMethods {
public int add(int numberA, int numberB) {
return numberA + numberB;
}
protected int multiply(int numberA, int numberB) {
return numberA * numberB;
}
private double div(int numberA, int numberB) {
return numberA / numberB;
}
}
public class Main {
public static void main(String[] args) throws Exception {
GetMethods object = new GetMethods();
Class clazz = object.getClass();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println("Method name = " + method.getName());
System.out.println("Method return type = " + method.getReturnType().getName());
Class[] paramTypes = method.getParameterTypes();
for (Class c : paramTypes) {
System.out.println("Param type = " + c.getName());
}
}
Method method = clazz.getMethod("add", new Class[] { int.class, int.class });
System.out.println("Method name: " + method.getName());
}
}
Get the class name in a static method
public class Main{
public static void main(java.lang.String[] args) {
System.out.println("in " + new CurrentClassGetter().getClassName() + " class");
}
}
class CurrentClassGetter extends SecurityManager {
public String getClassName() {
return getClassContext()[1].getName();
}
}
Get the current method name
public class Main{
public static void main(String args[]) {
System.out.println
(new Exception().getStackTrace()[0].getMethodName());
}
}
Get the current method name With JDK1.5
public class Main {
public static void main(String args[]) {
trace(Thread.currentThread().getStackTrace());
}
public static void trace(StackTraceElement e[]) {
boolean doNext = false;
for (StackTraceElement s : e) {
if (doNext) {
System.out.println(s.getMethodName());
return;
}
doNext = s.getMethodName().equals("getStackTrace");
}
}
}
Get the methods of a class object
import java.lang.reflect.Method;
class GetMethods {
public int add(int numberA, int numberB) {
return numberA + numberB;
}
protected int multiply(int numberA, int numberB) {
return numberA * numberB;
}
private double div(int numberA, int numberB) {
return numberA / numberB;
}
}
public class Main {
public static void main(String[] args) throws Exception {
GetMethods object = new GetMethods();
Class clazz = object.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Method name = " + method.getName());
System.out.println("Method return type = " + method.getReturnType().getName());
Class[] paramTypes = method.getParameterTypes();
for (Class c : paramTypes) {
System.out.println("Param type = " + c.getName());
}
}
}
}
Getting the Methods of a Class Object: By obtaining a list of all declared methods
import java.lang.reflect.Method;
public class Main {
public static void main(String[] argv) throws Exception {
Class cls = java.lang.String.class;
Method[] methods = cls.getDeclaredMethods();
}
}
Getting the Methods of a Class Object: By obtaining a list of all public methods, both declared and inherited.
import java.lang.reflect.Method;
public class Main {
public static void main(String[] argv) throws Exception {
Class cls = java.lang.String.class;
Method[] methods = cls.getMethods();
for (int i = 0; i < methods.length; i++) {
Class returnType = methods[i].getReturnType();
Class[] paramTypes = methods[i].getParameterTypes();
System.out.println(methods[i]);
}
}
}
Getting the Methods of a Class Object: By obtaining a particular Method object.
import java.lang.reflect.Method;
public class Main {
public static void main(String[] argv) throws Exception {
Class cls = java.lang.String.class;
Method method = cls.getMethod("substring", new Class[] { int.class });
System.out.println(method);
}
}
Invoke a method using Method class
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
MyClass object = new MyClass();
Class clazz = object.getClass();
Method method = clazz.getMethod("add", new Class[] { int.class, int.class });
Object result = method.invoke(object, new Object[] { 10, 10 });
System.out.println("Result = " + result);
method = clazz.getMethod("multiply", new Class[] { int.class, int.class });
result = method.invoke(object, new Object[] { 10, 10 });
System.out.println("Result = " + result);
}
}
class MyClass{
public int add(int numberA, int numberB) {
return numberA + numberB;
}
public int multiply(int numberA, int numberB) {
return numberA * numberB;
}
public double div(int numberA, int numberB) {
return numberA / numberB;
}
}
Invoke method through Java Reflection API
/*
* Copyright (c) 2000 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.ru/javaexamples2.
*/
import java.awt.event.*;
import java.beans.*;
import java.lang.reflect.*;
import java.io.*;
import java.util.*;
/**
* This class represents a Method, the list of arguments to be passed to that
* method, and the object on which the method is to be invoked. The invoke()
* method invokes the method. The actionPerformed() method does the same thing,
* allowing this class to implement ActionListener and be used to respond to
* ActionEvents generated in a GUI or elsewhere. The static parse() method
* parses a string representation of a method and its arguments.
*/
public class Command implements ActionListener {
Method m; // The method to be invoked
Object target; // The object to invoke it on
Object[] args; // The arguments to pass to the method
// An empty array; used for methods with no arguments at all.
static final Object[] nullargs = new Object[] {};
/** This constructor creates a Command object for a no-arg method */
public Command(Object target, Method m) {
this(target, m, nullargs);
}
/**
* This constructor creates a Command object for a method that takes the
* specified array of arguments. Note that the parse() method provides
* another way to create a Command object
*/
public Command(Object target, Method m, Object[] args) {
this.target = target;
this.m = m;
this.args = args;
}
/**
* Invoke the Command by calling the method on its target, and passing the
* arguments. See also actionPerformed() which does not throw the checked
* exceptions that this method does.
*/
public void invoke() throws IllegalAccessException,
InvocationTargetException {
m.invoke(target, args); // Use reflection to invoke the method
}
/**
* This method implements the ActionListener interface. It is like invoke()
* except that it catches the exceptions thrown by that method and rethrows
* them as an unchecked RuntimeException
*/
public void actionPerformed(ActionEvent e) {
try {
invoke(); // Call the invoke method
} catch (InvocationTargetException ex) { // but handle the exceptions
throw new RuntimeException("Command: "
+ ex.getTargetException().toString());
} catch (IllegalAccessException ex) {
throw new RuntimeException("Command: " + ex.toString());
}
}
/**
* This static method creates a Command using the specified target object,
* and the specified string. The string should contain method name followed
* by an optional parenthesized comma-separated argument list and a
* semicolon. The arguments may be boolean, integer or double literals, or
* double-quoted strings. The parser is lenient about missing commas,
* semicolons and quotes, but throws an IOException if it cannot parse the
* string.
*/
public static Command parse(Object target, String text) throws IOException {
String methodname; // The name of the method
ArrayList args = new ArrayList(); // Hold arguments as we parse them.
ArrayList types = new ArrayList(); // Hold argument types.
// Convert the string into a character stream, and use the
// StreamTokenizer class to convert it into a stream of tokens
StreamTokenizer t = new StreamTokenizer(new StringReader(text));
// The first token must be the method name
int c = t.nextToken(); // read a token
if (c != t.TT_WORD) // check the token type
throw new IOException("Missing method name for command");
methodname = t.sval; // Remember the method name
// Now we either need a semicolon or a open paren
c = t.nextToken();
if (c == "(") { // If we see an open paren, then parse an arg list
for (;;) { // Loop "till end of arglist
c = t.nextToken(); // Read next token
if (c == ")") { // See if we"re done parsing arguments.
c = t.nextToken(); // If so, parse an optional semicolon
if (c != ";")
t.pushBack();
break; // Now stop the loop.
}
// Otherwise, the token is an argument; figure out its type
if (c == t.TT_WORD) {
// If the token is an identifier, parse boolean literals,
// and treat any other tokens as unquoted string literals.
if (t.sval.equals("true")) { // Boolean literal
args.add(Boolean.TRUE);
types.add(boolean.class);
} else if (t.sval.equals("false")) { // Boolean literal
args.add(Boolean.FALSE);
types.add(boolean.class);
} else { // Assume its a string
args.add(t.sval);
types.add(String.class);
}
} else if (c == """) { // If the token is a quoted string
args.add(t.sval);
types.add(String.class);
} else if (c == t.TT_NUMBER) { // If the token is a number
int i = (int) t.nval;
if (i == t.nval) { // Check if its an integer
// Note: this code treats a token like "2.0" as an int!
args.add(new Integer(i));
types.add(int.class);
} else { // Otherwise, its a double
args.add(new Double(t.nval));
types.add(double.class);
}
} else { // Any other token is an error
throw new IOException("Unexpected token " + t.sval
+ " in argument list of " + methodname + "().");
}
// Next should be a comma, but we don"t complain if its not
c = t.nextToken();
if (c != ",")
t.pushBack();
}
} else if (c != ";") { // if a method name is not followed by a paren
t.pushBack(); // then allow a semi-colon but don"t require it.
}
// We"ve parsed the argument list.
// Next, convert the lists of argument values and types to arrays
Object[] argValues = args.toArray();
Class[] argtypes = (Class[]) types.toArray(new Class[argValues.length]);
// At this point, we"ve got a method name, and arrays of argument
// values and types. Use reflection on the class of the target object
// to find a method with the given name and argument types. Throw
// an exception if we can"t find the named method.
Method method;
try {
method = target.getClass().getMethod(methodname, argtypes);
} catch (Exception e) {
throw new IOException("No such method found, or wrong argument "
+ "types: " + methodname);
}
// Finally, create and return a Command object, using the target object
// passed to this method, the Method object we obtained above, and
// the array of argument values we parsed from the string.
return new Command(target, method, argValues);
}
public static void main(String[] args) throws IOException {
javax.swing.JFrame f = new javax.swing.JFrame("Command Test");
javax.swing.JButton b1 = new javax.swing.JButton("Tick");
javax.swing.JButton b2 = new javax.swing.JButton("Tock");
javax.swing.JLabel label = new javax.swing.JLabel("Hello world");
java.awt.Container pane = f.getContentPane();
pane.add(b1, java.awt.BorderLayout.WEST);
pane.add(b2, java.awt.BorderLayout.EAST);
pane.add(label, java.awt.BorderLayout.NORTH);
b1.addActionListener(Command.parse(label, "setText(\"tick\");"));
b2.addActionListener(Command.parse(label, "setText(\"tock\");"));
f.pack();
f.show();
}
}
Invokes a method, masking with a runtime exception all the exceptions.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
/**
* Invokes a method, masking with a runtime exception all the exceptions.
*
* @param obj The object from which a method will be called.
* @param method The method to call.
* @param args The arguments of the method.
* @return The object returned, if the method is not "void".
* @since 2.0.7
*/
public static Object invokeMethod(Object obj, Method method, Object... args) {
try {
return method.invoke(obj, args);
} catch (IllegalArgumentException e) {
throw new RuntimeException("The arguments for ""
+ method.getName() + "" in class ""
+ obj.getClass().getName() + "" are not valid", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot access ""
+ method.getName() + "" in class ""
+ obj.getClass().getName() + """, e);
} catch (InvocationTargetException e) {
throw new RuntimeException(
"An exception has been thrown inside "" + method.getName()
+ "" in class "" + obj.getClass().getName() + """, e);
}
}
}
Load a method on the fly
import java.lang.reflect.Method;
public class MainClass {
public static void main(String[] args) throws Exception {
printTable(10, MethodReflection.class.getMethod("square",
new Class[] { double.class }));
printTable( 10, java.lang.Math.class.getMethod("sqrt",
new Class[] { double.class }));
}
public static double square(double x) {
return x * x;
}
public static void printTable(int n, Method f) {
System.out.println(f);
try {
Object[] args = { new Double(n) };
Double d = (Double) f.invoke(null, args);
double y = d.doubleValue();
System.out.println(y);
} catch (Exception e) {
System.out.println(e);
}
}
}
Make methods that have unspecified number of parameters:pass an array of Objects
public class Main {
public static void main(String args[]) {
myMethod(new Object[] { "value 1", new Integer(2), "value n" });
}
public static void myMethod(Object parms[]) {
for (int i = 0; i < parms.length; i++)
System.out.println(parms[i]);
}
}
Method modifiers: isSynthetic(), m.isVarArgs(), m.isBridge()
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import static java.lang.System.out;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class MethodModifierSpy {
private static int count;
private static synchronized void inc() {
count++;
}
private static synchronized int cnt() {
return count;
}
public static void main(String... args) {
try {
Class<?> c = Class.forName(args[0]);
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
if (!m.getName().equals(args[1])) {
continue;
}
out.format("%s%n", m.toGenericString());
out.format(" Modifiers: %s%n", Modifier.toString(m.getModifiers()));
out.format(" [ synthetic=%-5b var_args=%-5b bridge=%-5b ]%n", m
.isSynthetic(), m.isVarArgs(), m.isBridge());
inc();
}
out.format("%d matching overload%s found%n", cnt(), (cnt() == 1 ? ""
: "s"));
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
Method Reflection
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class MainClass {
public static void main(String[] args) {
String name = "java.util.Date";
try {
Class cl = Class.forName(name);
Class supercl = cl.getSuperclass();
System.out.println("class " + name);
System.out.println("Its methods:");
printMethods(cl);
System.out.println();
} catch (ClassNotFoundException e) {
System.out.println("Class not found.");
}
}
public static void printMethods(Class cl) {
Method[] methods = cl.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
Class retType = m.getReturnType();
Class[] paramTypes = m.getParameterTypes();
String name = m.getName();
System.out.print(Modifier.toString(m.getModifiers()));
System.out.print(" " + retType.getName() + " " + name + "(");
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0)
System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
}
}
Object Reflection: invoke methods
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies. Please refer to
* the file "copyright.html" for further important copyright and licensing
* information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES.
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class SampleInvoke {
public static void main(String[] args) {
String firstWord = "Hello ";
String secondWord = "everybody.";
String bothWords = append(firstWord, secondWord);
System.out.println(bothWords);
}
public static String append(String firstWord, String secondWord) {
String result = null;
Class c = String.class;
Class[] parameterTypes = new Class[] { String.class };
Method concatMethod;
Object[] arguments = new Object[] { secondWord };
try {
concatMethod = c.getMethod("concat", parameterTypes);
result = (String) concatMethod.invoke(firstWord, arguments);
} catch (NoSuchMethodException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
return result;
}
}
Returns method with the specified name
// $Id: ReflectionHelper.java 16271 2009-04-07 20:20:12Z hardy.ferentschik $
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Some reflection utility methods.
*
* @author Hardy Ferentschik
*/
public class ReflectionHelper {
/**
* Returns the method with the specified name or <code>null</code> if it does not exist.
*
* @param clazz The class to check.
* @param methodName The method name.
*
* @return Returns the method with the specified name or <code>null</code> if it does not exist.
*/
public static Method getMethod(Class<?> clazz, String methodName) {
try {
return clazz.getMethod( "get" + methodName.substring( 0, 1 ).toUpperCase() + methodName.substring( 1 ) );
}
catch ( NoSuchMethodException e ) {
return null;
}
}
}
Show loading a class and finding and calling its Main method
import java.lang.reflect.Method;
/**
* Show loading a class and finding and calling its Main method.
*
* @author Ian F. Darwin, http://www.darwinsys.ru/
* @version $Id: InvokeMain.java,v 1.3 2004/02/09 03:33:54 ian Exp $
*/
public class InvokeMain {
public static void main(String[] argv) {
//+
try {
// First, find the class.
Class c = Class.forName("InvokeMain"); // RECURSION
System.out.println(c);
// Create the array of Argument Types
Class[] argTypes = { argv.getClass(), // array is Object!
};
// Now find the method
Method m = c.getMethod("main", argTypes);
System.out.println(m);
// Create the actual argument array
Object passedArgv[] = { argv };
// Now invoke the method.
m.invoke(null, passedArgv);
} catch (Exception e) {
System.err.println(e);
}
//-
}
}
Sorts methods according to their name, number of parameters, and parameter types.
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.lang.reflect.Method;
import java.util.ruparator;
/**
* Sorts methods according to their name, number of parameters, and parameter
* types.
*/
public class MethodComparator implements Comparator<Method> {
public int compare(Method m1, Method m2) {
int val = m1.getName().rupareTo(m2.getName());
if (val == 0) {
val = m1.getParameterTypes().length - m2.getParameterTypes().length;
if (val == 0) {
Class[] types1 = m1.getParameterTypes();
Class[] types2 = m2.getParameterTypes();
for (int i = 0; i < types1.length; i++) {
val = types1[i].getName().rupareTo(types2[i].getName());
if (val != 0) {
break;
}
}
}
}
return val;
}
}
The next example calls a class method with 2 arguments:
import java.lang.reflect.Method;
public class Main{
static void invoke(String aClass, String aMethod, Class[] params, Object[] args) {
try {
Class c = Class.forName(aClass);
Method m = c.getDeclaredMethod(aMethod, params);
Object i = c.newInstance();
Object r = m.invoke(i, args);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
invoke("Class1", "say", new Class[] { String.class, String.class }, new Object[] {
new String("Hello"), new String("World") });
}
}
class Class1 {
public void say(String s1, String s2) {
System.out.println(s1 + " " + s2);
}
}
To get the calling method
public class Main {
public static void main(String args[]) {
anotherLayout();
}
public static void anotherLayout(){
new Main().doit();
}
public void doit() {
System.out.println(
Thread.currentThread().getStackTrace()[3].getMethodName());
}
}
Using reflection to show all the methods of a class,
// : c10:ShowMethods.java
// Using reflection to show all the methods of a class,
// even if the methods are defined in the base class.
// {Args: ShowMethods}
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class ShowMethods {
private static final String usage = "usage: \n"
+ "ShowMethods qualified.class.name\n"
+ "To show all methods in class or: \n"
+ "ShowMethods qualified.class.name word\n"
+ "To search for methods involving "word"";
private static Pattern p = Pattern.rupile("\\w+\\.");
public static void main(String[] args) {
if (args.length < 1) {
System.out.println(usage);
System.exit(0);
}
int lines = 0;
try {
Class c = Class.forName(args[0]);
Method[] m = c.getMethods();
Constructor[] ctor = c.getConstructors();
if (args.length == 1) {
for (int i = 0; i < m.length; i++)
System.out.println(p.matcher(m[i].toString())
.replaceAll(""));
for (int i = 0; i < ctor.length; i++)
System.out.println(p.matcher(ctor[i].toString())
.replaceAll(""));
lines = m.length + ctor.length;
} else {
for (int i = 0; i < m.length; i++)
if (m[i].toString().indexOf(args[1]) != -1) {
System.out.println(p.matcher(m[i].toString())
.replaceAll(""));
lines++;
}
for (int i = 0; i < ctor.length; i++)
if (ctor[i].toString().indexOf(args[1]) != -1) {
System.out.println(p.matcher(ctor[i].toString())
.replaceAll(""));
lines++;
}
}
} catch (ClassNotFoundException e) {
System.out.println("No such class: " + e);
}
}
} ///:~