Java/Reflection/Generic
Содержание
- 1 All information about a class
- 2 A wrapper around reflection to resolve generics.
- 3 Class Declaration Spy
- 4 Generic Class reflection
- 5 Generic method reflection
- 6 Get all implemented generic interfaces
- 7 Get all interface and object classes that are generalizations of the provided class
- 8 get Exception Types and get Generic Exception Types
- 9 Get field type and generic type by field name
- 10 get Generic Parameter Types from Constructor
- 11 Get Generic Super class
- 12 get Parameter Types and get Generic ParameterTypes
- 13 get Return Type and get Generic Return Type
- 14 If right-hand side type may be assigned to the left-hand side type following the Java generics rules.
All information about a class
<source lang="java">
/*
* 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.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; enum ClassMember {
CONSTRUCTOR, FIELD, METHOD, CLASS, ALL
} public class ClassSpy {
public static void main(String... args) { try { Class<?> c = Class.forName(args[0]); out.format("Class:%n %s%n%n", c.getCanonicalName()); Package p = c.getPackage(); out.format("Package:%n %s%n%n", (p != null ? p.getName() : "-- No Package --")); for (int i = 1; i < args.length; i++) { switch (ClassMember.valueOf(args[i])) { case CONSTRUCTOR: printMembers(c.getConstructors(), "Constructor"); break; case FIELD: printMembers(c.getFields(), "Fields"); break; case METHOD: printMembers(c.getMethods(), "Methods"); break; case CLASS: printClasses(c); break; case ALL: printMembers(c.getConstructors(), "Constuctors"); printMembers(c.getFields(), "Fields"); printMembers(c.getMethods(), "Methods"); printClasses(c); break; default: assert false; } } // production code should handle these exceptions more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } } private static void printMembers(Member[] mbrs, String s) { out.format("%s:%n", s); for (Member mbr : mbrs) { if (mbr instanceof Field) out.format(" %s%n", ((Field) mbr).toGenericString()); else if (mbr instanceof Constructor) out.format(" %s%n", ((Constructor) mbr).toGenericString()); else if (mbr instanceof Method) out.format(" %s%n", ((Method) mbr).toGenericString()); } if (mbrs.length == 0) out.format(" -- No %s --%n", s); out.format("%n"); } private static void printClasses(Class<?> c) { out.format("Classes:%n"); Class<?>[] clss = c.getClasses(); for (Class<?> cls : clss) out.format(" %s%n", cls.getCanonicalName()); if (clss.length == 0) out.format(" -- No member interfaces, classes, or enums --%n"); out.format("%n"); }
}
</source>
A wrapper around reflection to resolve generics.
<source lang="java">
/*
* 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.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map;
/**
* A wrapper around reflection to resolve generics. * * @author Simone Gianni <simoneg@apache.org> */
// TODO there is vast space for caching and optimizations here! public class GenericClass {
private Class<?> myclass = null; private Map<String, Class<?>> genericMap = new HashMap<String, Class<?>>(); private Map<String, String> reverseIntermediate = new HashMap<String, String>(); public static GenericClass forClass(Class<?> concrete) { return new GenericClass(concrete); } public static GenericClass forField(Field field) { return forGenericType(field.getGenericType()); } public static GenericClass forReturnType(Method method) { return forGenericType(method.getGenericReturnType()); } public static GenericClass forParameter(Method method, int index) { return forGenericType(method.getGenericParameterTypes()[index]); } public static GenericClass forGenericType(Type type) { if (type instanceof Class) { return forClass((Class<?>) type); } else if (type instanceof ParameterizedType) { return new GenericClass((ParameterizedType) type); } else { return forClass(Object.class); // throw new MagmaException("Dont know how to build a GenericClass out of // {0}", type.getClass()); } } private GenericClass(Class<?> concrete) { TypeVariable<?>[] parameters = concrete.getTypeParameters(); // if (parameters.length > 0) throw new MagmaException("Cannot parse {0}, it // is a generic class, use a concrete class instead", concrete); myclass = concrete; recurse(concrete); coalesceMap(); } private GenericClass(ParameterizedType type) { myclass = (Class<?>) type.getRawType(); recurse(myclass, myclass, type); coalesceMap(); } private void coalesceMap() { int cnt = reverseIntermediate.size(); while (reverseIntermediate.size() > 0 && cnt > 0) { for (Iterator<Map.Entry<String, String>> iterator = this.reverseIntermediate.entrySet() .iterator(); iterator.hasNext();) { Map.Entry<String, String> entry = iterator.next(); String target = entry.getValue(); String search = entry.getKey(); Class<?> clazz = genericMap.get(search); if (clazz == null) continue; if (genericMap.containsKey(target)) throw new RuntimeException( "Impossible situation, it"s a bug : {0} generic is both {1} and bound to {2}" + target + genericMap.get(target) + search); genericMap.put(target, clazz); iterator.remove(); } cnt--; } if (reverseIntermediate.size() > 0) { for (Iterator<Map.Entry<String, String>> iterator = this.reverseIntermediate.entrySet() .iterator(); iterator.hasNext();) { Map.Entry<String, String> entry = iterator.next(); String target = entry.getValue(); String search = entry.getKey(); Class<?> clazz = genericMap.get(search); if (clazz == null) clazz = Object.class; if (genericMap.containsKey(target)) throw new RuntimeException( "Impossible situation, it"s a bug : {0} generic is both {1} and bound to {2}"+ target+ genericMap.get(target)+ search); genericMap.put(target, clazz); } } } public Class<?> getBaseClass() { return this.myclass; } private void recurse(Class<?> clazz, Class<?> simplesup, ParameterizedType partype) { Type[] typeArguments = partype.getActualTypeArguments(); TypeVariable<?>[] parameters = simplesup.getTypeParameters(); for (int i = 0; i < typeArguments.length; i++) { if (typeArguments[i] instanceof Class) { genericMap.put(simplesup.getName() + "--" + parameters[i].getName(), (Class) typeArguments[i]); } else if (typeArguments[i] instanceof TypeVariable) { reverseIntermediate.put(clazz.getName() + "--" + ((TypeVariable<?>) typeArguments[i]).getName(), simplesup.getName() + "--" + parameters[i].getName()); } } recurse(simplesup); } private void recurse(Class<?> clazz) { Type supclass = clazz.getGenericSuperclass(); Class simplesup = clazz.getSuperclass(); if (supclass == null) return; if (supclass instanceof ParameterizedType) { recurse(clazz, simplesup, (ParameterizedType) supclass); } else { recurse(simplesup); } } /** * Return real, "generics dereferenced", parameter types for the given method. * * @param method * The method to analyze * @return The real classes, dereferencing generics */ public GenericClass[] getParameterTypes(Method method) { Class<?> declaring = method.getDeclaringClass(); String declname = declaring.getName(); Type[] parameterTypes = method.getGenericParameterTypes(); GenericClass[] ret = new GenericClass[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { Type type = parameterTypes[i]; if (type instanceof Class) { ret[i] = forClass((Class<?>) type); } else if (type instanceof TypeVariable) { String name = ((TypeVariable<?>) type).getName(); Class<?> sub = genericMap.get(declname + "--" + name); if (sub == null) sub = Object.class; ret[i] = forClass(sub); } else { ret[i] = forGenericType(type); } } return ret; } public GenericClass resolveType(Type type) { if (type instanceof Class) { return forClass((Class<?>) type); } else if (type instanceof TypeVariable) { GenericDeclaration gd = ((TypeVariable<?>) type).getGenericDeclaration(); Class<?> acclass = null; if (gd instanceof Class) { acclass = (Class<?>) gd; } else if (gd instanceof Method) { acclass = ((Method) gd).getDeclaringClass(); } else if (gd instanceof Constructor) { acclass = ((Constructor<?>) gd).getDeclaringClass(); } String name = ((TypeVariable<?>) type).getName(); return forClass(genericMap.get(acclass.getName() + "--" + name)); } else { return forGenericType(type); } } /** * Search for all occurrencies of a specific method.*
* The type parameters passed in may be Class or null. If they are null, that * means that we don"t know which class they should be, if they are a class, * that means we are searching for that class, and the comparison is made on * dereferenced generics. *
** Specifying no parameter types explicitly means "a method without * parameters". *
* * @param name * The name of the method * @param parameterTypes * The types of the parameters * @return A list of {@link MethodDef}, ordered with methods from current * class first, then method from superclass and so on. */ public List<MethodDef> findMethods(String name, Class<?>... parameterTypes) { List<MethodDef> founds = new ArrayList<MethodDef>(); Class<?> current = myclass; while (current != null) { Method[] methods = current.getDeclaredMethods(); for (Method method : methods) { if (!method.isBridge() && !method.isSynthetic() && method.getName().equals(name)) { Type[] types = method.getGenericParameterTypes(); if (types.length == parameterTypes.length) { GenericClass[] genericClasses = getParameterTypes(method); Class<?>[] classes = toRawClasses(genericClasses); boolean good = true; for (int i = 0; i < types.length; i++) { if (parameterTypes[i] != null) { if (!classes[i].equals(parameterTypes[i])) { good = false; break; } } } if (good) { MethodDef def = new MethodDef(method, genericClasses); if (!founds.contains(def)) founds.add(def); } } } } current = current.getSuperclass(); } return founds; } public static Class<?>[] toRawClasses(GenericClass[] genclasses) { Class<?>[] ret = new Class<?>[genclasses.length]; for (int i = 0; i < genclasses.length; i++) { ret[i] = genclasses[i].getBaseClass(); } return ret; } /** * Search for all methods having that name, no matter which parameter they * take. * * @param name * The name of the methods * @return A list of {@link MethodDef}, ordered with methods from current * class first, then method from superclass and so on. */ public List<MethodDef> findAllMethods(String name) { List<MethodDef> founds = new ArrayList<MethodDef>(); Class<?> current = myclass; while (current != null) { Method[] methods = current.getDeclaredMethods(); for (Method method : methods) { if (!method.isBridge() && !method.isSynthetic() && method.getName().equals(name)) { MethodDef def = new MethodDef(method); if (!founds.contains(def)) founds.add(def); } } current = current.getSuperclass(); } return founds; } public List<MethodDef> getMethods() { List<MethodDef> founds = new ArrayList<MethodDef>(); Class<?> current = myclass; while (current != null) { Method[] methods = current.getDeclaredMethods(); for (Method method : methods) { if (!method.isBridge() && !method.isSynthetic()) { MethodDef def = new MethodDef(method); if (!founds.contains(def)) founds.add(def); } } current = current.getSuperclass(); } return founds; } @Override public boolean equals(Object obj) { if (!(obj instanceof GenericClass)) return false; GenericClass oth = (GenericClass) obj; return this.getBaseClass().equals(oth.getBaseClass()); } public class MethodDef { private Method method = null; private GenericClass[] params = null; MethodDef(Method m) { this.method = m; } MethodDef(Method m, GenericClass[] params) { this.method = m; this.params = params; } public String getName() { return this.method.getName(); } public Method getBaseMethod() { return this.method; } public GenericClass[] getParameterTypes() { if (this.params == null) { this.params = GenericClass.this.getParameterTypes(method); } return this.params; } public GenericClass getReturnType() { return resolveType(method.getGenericReturnType()); } @Override public boolean equals(Object other) { if (!(other instanceof MethodDef)) return false; MethodDef oth = (MethodDef) other; return (method.getName().equals(oth.method.getName())) && (Arrays.equals(getParameterTypes(), oth.getParameterTypes())); } public Class<?> getDeclaringClass() { return this.method.getDeclaringClass(); } }
}
</source>
Class Declaration Spy
<source lang="java">
/*
* 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.annotation.Annotation; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.List; public class ClassDeclarationSpy {
public static void main(String... args) { try { Class<?> c = Class.forName(args[0]); out.format("Class:%n %s%n%n", c.getCanonicalName()); out.format("Modifiers:%n %s%n%n", Modifier.toString(c.getModifiers())); out.format("Type Parameters:%n"); TypeVariable[] tv = c.getTypeParameters(); if (tv.length != 0) { out.format(" "); for (TypeVariable t : tv) out.format("%s ", t.getName()); out.format("%n%n"); } else { out.format(" -- No Type Parameters --%n%n"); } out.format("Implemented Interfaces:%n"); Type[] intfs = c.getGenericInterfaces(); if (intfs.length != 0) { for (Type intf : intfs) out.format(" %s%n", intf.toString()); out.format("%n"); } else { out.format(" -- No Implemented Interfaces --%n%n"); } out.format("Inheritance Path:%n"); List<Class> l = new ArrayList<Class>(); printAncestor(c, l); if (l.size() != 0) { for (Class<?> cl : l) out.format(" %s%n", cl.getCanonicalName()); out.format("%n"); } else { out.format(" -- No Super Classes --%n%n"); } out.format("Annotations:%n"); Annotation[] ann = c.getAnnotations(); if (ann.length != 0) { for (Annotation a : ann) out.format(" %s%n", a.toString()); out.format("%n"); } else { out.format(" -- No Annotations --%n%n"); } // production code should handle this exception more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } } private static void printAncestor(Class<?> c, List<Class> l) { Class<?> ancestor = c.getSuperclass(); if (ancestor != null) { l.add(ancestor); printAncestor(ancestor, l); } }
}
</source>
Generic Class reflection
<source lang="java">
/*
* 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. */
class Cls {
private Cls() { }
} public class ClassTrouble {
public static void main(String... args) { try { Class<?> c = Class.forName("Cls"); c.newInstance(); // InstantiationException // production code should handle these exceptions more gracefully } catch (InstantiationException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } catch (ClassNotFoundException x) { x.printStackTrace(); } }
}
</source>
Generic method reflection
<source lang="java">
/*
* 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.Method; public class MethodTrouble<T> {
public void lookup(T t) { } public void find(Integer i) { } public static void main(String... args) { try { String mName = args[0]; Class cArg = Class.forName(args[1]); Class<?> c = (new MethodTrouble<Integer>()).getClass(); Method m = c.getMethod(mName, cArg); System.out.format("Found:%n %s%n", m.toGenericString()); // production code should handle these exceptions more gracefully } catch (NoSuchMethodException x) { x.printStackTrace(); } catch (ClassNotFoundException x) { x.printStackTrace(); } }
}
</source>
Get all implemented generic interfaces
<source lang="java">
import java.lang.reflect.Type; import javax.xml.transform.sax.SAXSource; public class GetGenericInterfaces {
public static void main(String[] args) { try { Type[] ts = SAXSource.class.getGenericInterfaces(); for (int i = 0; i < ts.length; i++) { System.out.println(ts[i]); } } catch (SecurityException e) { e.printStackTrace(); } }
}
</source>
Get all interface and object classes that are generalizations of the provided class
<source lang="java">
/*
* The contents of this file are subject to the Sapient Public License * Version 1.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://carbon.sf.net/License.html. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is The Carbon Component Framework. * * The Initial Developer of the Original Code is Sapient Corporation * * Copyright (C) 2003 Sapient Corporation. All Rights Reserved. */
import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /**
* * * Copyright 2003 Sapient * @since carbon 2.0 * @author Greg Hinkle, March 2003 * @version $Revision: 1.5 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $) */
public class ClassUtil {
/** * Retrieves all interfaces implemented by a specified interface * including all recursively extended interfaces and the classes supplied * int the parameter. * @param childInterfaces a set of interfaces * @return Class[] an array of interfaces that includes those specifed * in childInterfaces plus all of those interfaces" super interfaces */ public static Class[] getSuperInterfaces(Class[] childInterfaces) { List allInterfaces = new ArrayList(); for (int i = 0; i < childInterfaces.length; i++) { allInterfaces.add(childInterfaces[i]); allInterfaces.addAll( Arrays.asList( getSuperInterfaces(childInterfaces[i].getInterfaces()))); } return (Class[]) allInterfaces.toArray(new Class[allInterfaces.size()]); } /** * Builds an unordered set of all interface and object classes that * are generalizations of the provided class. * @param classObject the class to find generalization of. * @return a Set of class objects. */ public static Set getGeneralizations(Class classObject) { Set generalizations = new HashSet(); generalizations.add(classObject); Class superClass = classObject.getSuperclass(); if (superClass != null) { generalizations.addAll(getGeneralizations(superClass)); } Class[] superInterfaces = classObject.getInterfaces(); for (int i = 0; i < superInterfaces.length; i++) { Class superInterface = superInterfaces[i]; generalizations.addAll(getGeneralizations(superInterface)); } return generalizations; }
}
</source>
get Exception Types and get Generic Exception Types
<source lang="java">
/*
* 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.Type; public class MethodSpy {
private static final String fmt = "%24s: %s%n"; // for the morbidly curious <E extends RuntimeException> void genericThrow() throws E { } 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()); Class<?>[] xType = m.getExceptionTypes(); Type[] gxType = m.getGenericExceptionTypes(); for (int i = 0; i < xType.length; i++) { out.format(fmt, "ExceptionType", xType[i]); out.format(fmt, "GenericExceptionType", gxType[i]); } } // production code should handle these exceptions more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } }
}
</source>
Get field type and generic type by field name
<source lang="java">
/*
* 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.Field; import java.util.List; public class FieldSpy<T> {
public boolean[][] b = { { false, false }, { true, true } }; public String name = "Alice"; public List<Integer> list; public T val; public static void main(String... args) { try { Class<?> c = Class.forName("FieldSpy"); Field f = c.getField("name"); System.out.format("Type: %s%n", f.getType()); System.out.format("GenericType: %s%n", f.getGenericType()); // production code should handle these exceptions more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } catch (NoSuchFieldException x) { x.printStackTrace(); } }
}
</source>
get Generic Parameter Types from Constructor
<source lang="java">
/*
* 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.Constructor; import java.lang.reflect.Type; public class ConstructorSift {
public static void main(String... args) { try { Class<?> cArg = Class.forName(args[1]); Class<?> c = Class.forName(args[0]); Constructor[] allConstructors = c.getDeclaredConstructors(); for (Constructor ctor : allConstructors) { Class<?>[] pType = ctor.getParameterTypes(); for (int i = 0; i < pType.length; i++) { if (pType[i].equals(cArg)) { out.format("%s%n", ctor.toGenericString()); Type[] gpType = ctor.getGenericParameterTypes(); for (int j = 0; j < gpType.length; j++) { char ch = (pType[j].equals(cArg) ? "*" : " "); out.format("%7c%s[%d]: %s%n", ch, "GenericParameterType", j, gpType[j]); } break; } } } // production code should handle this exception more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } }
}
</source>
Get Generic Super class
<source lang="java">
import java.lang.reflect.Type; import java.util.ArrayList; import javax.xml.transform.sax.SAXSource;
public class GetGenericSuperclass {
public static void main(String[] args) { try { Class< ? super SAXSource> ts = SAXSource.class.getSuperclass(); System.out.println(ts); } catch (SecurityException e) { e.printStackTrace(); } try { Type t = ArrayList.class.getGenericSuperclass(); System.out.println(t); } catch (SecurityException e) { e.printStackTrace(); } try { Class[] is = SAXSource.class.getInterfaces(); for(int i=0;i<is.length;i++){ System.out.println(is[i]); } } catch (SecurityException e) { e.printStackTrace(); } }
}
</source>
get Parameter Types and get Generic ParameterTypes
<source lang="java">
/*
* 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.Type; public class MethodSpy {
private static final String fmt = "%24s: %s%n"; // for the morbidly curious <E extends RuntimeException> void genericThrow() throws E { } 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(fmt, "ReturnType", m.getReturnType()); out.format(fmt, "GenericReturnType", m.getGenericReturnType()); Class<?>[] pType = m.getParameterTypes(); Type[] gpType = m.getGenericParameterTypes(); for (int i = 0; i < pType.length; i++) { out.format(fmt, "ParameterType", pType[i]); out.format(fmt, "GenericParameterType", gpType[i]); }
} // production code should handle these exceptions more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } }
}
</source>
get Return Type and get Generic Return Type
<source lang="java">
/*
* 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.Type; public class MethodSpy {
private static final String fmt = "%24s: %s%n"; // for the morbidly curious <E extends RuntimeException> void genericThrow() throws E { } 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(fmt, "ReturnType", m.getReturnType()); out.format(fmt, "GenericReturnType", m.getGenericReturnType());
} // production code should handle these exceptions more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } }
}
</source>
If right-hand side type may be assigned to the left-hand side type following the Java generics rules.
<source lang="java">
/*
* Copyright 2002-2007 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.beans.Introspector; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.Assert; import sun.rmi.runtime.Log; /**
* Utility to work with Java 5 generic type parameters. * Mainly for internal use within the framework. * * @author Ramnivas Laddad * @author Juergen Hoeller * @since 2.0.7 */
public abstract class TypeUtils {
/** * Check if the right-hand side type may be assigned to the left-hand side * type following the Java generics rules. * @param lhsType the target type * @param rhsType the value type that should be assigned to the target type * @return true if rhs is assignable to lhs */ public static boolean isAssignable(Type lhsType, Type rhsType) { if (lhsType.equals(rhsType)) { return true; } if (lhsType instanceof Class && rhsType instanceof Class) { return ClassUtils.isAssignable((Class) lhsType, (Class) rhsType); } if (lhsType instanceof ParameterizedType && rhsType instanceof ParameterizedType) { return isAssignable((ParameterizedType) lhsType, (ParameterizedType) rhsType); } if (lhsType instanceof WildcardType) { return isAssignable((WildcardType) lhsType, rhsType); } return false; } private static boolean isAssignable(ParameterizedType lhsType, ParameterizedType rhsType) { if (lhsType.equals(rhsType)) { return true; } Type[] lhsTypeArguments = lhsType.getActualTypeArguments(); Type[] rhsTypeArguments = rhsType.getActualTypeArguments(); if (lhsTypeArguments.length != rhsTypeArguments.length) { return false; } for (int size = lhsTypeArguments.length, i = 0; i < size; ++i) { Type lhsArg = lhsTypeArguments[i]; Type rhsArg = rhsTypeArguments[i]; if (!lhsArg.equals(rhsArg) && !(lhsArg instanceof WildcardType && isAssignable((WildcardType) lhsArg, rhsArg))) { return false; } } return true; } private static boolean isAssignable(WildcardType lhsType, Type rhsType) { Type[] upperBounds = lhsType.getUpperBounds(); Type[] lowerBounds = lhsType.getLowerBounds(); for (int size = upperBounds.length, i = 0; i < size; ++i) { if (!isAssignable(upperBounds[i], rhsType)) { return false; } } for (int size = lowerBounds.length, i = 0; i < size; ++i) { if (!isAssignable(rhsType, lowerBounds[i])) { return false; } } return true; }
} /*
* Copyright 2002-2007 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. */
/**
* Miscellaneous class utility methods. Mainly for internal use within the * framework; consider Jakarta"s Commons Lang for a more comprehensive suite * of class utilities. * * @author Keith Donald * @author Rob Harrop * @author Juergen Hoeller * @since 1.1 * @see TypeUtils * @see ReflectionUtils */ abstract class ClassUtils { /** Suffix for array class names: "[]" */ public static final String ARRAY_SUFFIX = "[]"; /** Prefix for internal array class names: "[L" */ private static final String INTERNAL_ARRAY_PREFIX = "[L"; /** The package separator character "." */ private static final char PACKAGE_SEPARATOR = "."; /** The inner class separator character "$" */ private static final char INNER_CLASS_SEPARATOR = "$"; /** The CGLIB class separator character "$$" */ public static final String CGLIB_CLASS_SEPARATOR = "$$"; /** The ".class" file suffix */ public static final String CLASS_FILE_SUFFIX = ".class";
/** * Map with primitive wrapper type as key and corresponding primitive * type as value, for example: Integer.class -> int.class. */ private static final Map primitiveWrapperTypeMap = new HashMap(8); /** * Map with primitive type name as key and corresponding primitive * type as value, for example: "int" -> "int.class". */ private static final Map primitiveTypeNameMap = new HashMap(16);
static { primitiveWrapperTypeMap.put(Boolean.class, boolean.class); primitiveWrapperTypeMap.put(Byte.class, byte.class); primitiveWrapperTypeMap.put(Character.class, char.class); primitiveWrapperTypeMap.put(Double.class, double.class); primitiveWrapperTypeMap.put(Float.class, float.class); primitiveWrapperTypeMap.put(Integer.class, int.class); primitiveWrapperTypeMap.put(Long.class, long.class); primitiveWrapperTypeMap.put(Short.class, short.class); Set primitiveTypeNames = new HashSet(16); primitiveTypeNames.addAll(primitiveWrapperTypeMap.values()); primitiveTypeNames.addAll(Arrays.asList(new Class[] { boolean[].class, byte[].class, char[].class, double[].class, float[].class, int[].class, long[].class, short[].class})); for (Iterator it = primitiveTypeNames.iterator(); it.hasNext();) { Class primitiveClass = (Class) it.next(); primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass); } } /** * Check if the right-hand side type may be assigned to the left-hand side * type, assuming setting by reflection. Considers primitive wrapper * classes as assignable to the corresponding primitive types. * @param lhsType the target type * @param rhsType the value type that should be assigned to the target type * @return if the target type is assignable from the value type * @see TypeUtils#isAssignable */ public static boolean isAssignable(Class lhsType, Class rhsType) { return (lhsType.isAssignableFrom(rhsType) || lhsType.equals(primitiveWrapperTypeMap.get(rhsType))); }
}
</source>