Java/Reflection/Generic

Материал из Java эксперт
Версия от 06:01, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

All information about a class

   
/*
 * 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");
  }
}





A wrapper around reflection to resolve generics.

 
/*
 * 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.
   * <p>
   * 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.
   * </p>
   * <p>
   * Specifying no parameter types explicitly means "a method without
   * parameters".
   * </p>
   * 
   * @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();
    }
  }
}





Class Declaration Spy

   
/*
 * 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);
    }
  }
}





Generic Class reflection

   
/*
 * 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();
    }
  }
}





Generic method reflection

   
/*
 * 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();
    }
  }
}





Get all implemented generic interfaces

   
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();
    }
  }
}





Get all interface and object classes that are generalizations of the provided class

    
/*
 * 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 <b>unordered</b> 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;
    }
}





get Exception Types and get Generic Exception Types

   
        
/*
 * 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();
    }
  }
}





Get field type and generic type by field name

   
/*
 * 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();
    }
  }
}





get Generic Parameter Types from Constructor

   
/*
 * 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();
    }
  }
}





Get Generic Super class

   
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();
        }           
    }
}





get Parameter Types and get Generic ParameterTypes

   
        
/*
 * 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();
    }
  }
}





get Return Type and get Generic Return Type

   
/*
 * 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();
    }
  }
}





If right-hand side type may be assigned to the left-hand side type following the Java generics rules.

    
/*
 * 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)));
  }
}