content: import otherpackage.OtherPackageClass;
  
  import java.io.Serializable;
  import java.lang.reflect.AbstractMethod;
  import java.lang.reflect.AccessibleObject;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Field;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.lang.reflect.Type;
  import java.lang.reflect.TypeVariable;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  
  public class ClassAttrs {
      ClassAttrs() {
          /* local, not anonymous, not member */
          class ConsInnerNamed {
              public void showMe() {
                  printClassAttrs(this.getClass());
              }
          }
  
          ConsInnerNamed cinner = new ConsInnerNamed();
          cinner.showMe();
      }
  
      public class PublicInnerClass {
      }
  
      protected class ProtectedInnerClass {
      }
  
      private class PrivateInnerClass {
      }
  
      class PackagePrivateInnerClass {
      }
  
      public interface PublicInnerInterface {
      }
  
      protected interface ProtectedInnerInterface {
      }
  
      private interface PrivateInnerInterface {
      }
  
      interface PackagePrivateInnerInterface {
      }
  
      private static void showModifiers(Class<?> c) {
          System.out.println(Modifier.toString(c.getModifiers()) + " " + c.getName());
      }
  
      // https://code.google.com/p/android/issues/detail?id=56267
      private static void test56267() {
          // Primitive classes.
          showModifiers(int.class);
          showModifiers(int[].class);
  
          // Regular classes.
          showModifiers(Object.class);
          showModifiers(Object[].class);
  
          // Inner classes.
          showModifiers(PublicInnerClass.class);
          showModifiers(PublicInnerClass[].class);
          showModifiers(ProtectedInnerClass.class);
          showModifiers(ProtectedInnerClass[].class);
          showModifiers(PrivateInnerClass.class);
          showModifiers(PrivateInnerClass[].class);
          showModifiers(PackagePrivateInnerClass.class);
          showModifiers(PackagePrivateInnerClass[].class);
  
          // Regular interfaces.
          showModifiers(Serializable.class);
          showModifiers(Serializable[].class);
  
          // Inner interfaces.
          showModifiers(PublicInnerInterface.class);
          showModifiers(PublicInnerInterface[].class);
          showModifiers(ProtectedInnerInterface.class);
          showModifiers(ProtectedInnerInterface[].class);
          showModifiers(PrivateInnerInterface.class);
          showModifiers(PrivateInnerInterface[].class);
          showModifiers(PackagePrivateInnerInterface.class);
          showModifiers(PackagePrivateInnerInterface[].class);
      }
  
      public static void main() {
          test56267();
  
          printClassAttrs(ClassAttrs.class);
          printClassAttrs(OtherClass.class);
          printClassAttrs(OtherPackageClass.class);
  
          /* local, not anonymous, not member */
          class InnerNamed {
              public void showMe() {
                  printClassAttrs(this.getClass());
              }
          }
          InnerNamed inner = new InnerNamed();
          inner.showMe();
  
          ClassAttrs attrs = new ClassAttrs();
  
          /* anonymous, not local, not member */
          printClassAttrs((new OtherClass() { int i = 5; }).getClass());
  
          /* member, not anonymous, not local */
          printClassAttrs(MemberClass.class);
  
          /* fancy */
          printClassAttrs(FancyClass.class);
  
          try {
              Constructor cons;
              cons = MemberClass.class.getConstructor(
                      new Class[] { MemberClass.class });
              System.out.println("constructor signature: "
                      + getSignatureAttribute(cons));
  
              Method meth;
              meth = MemberClass.class.getMethod("foo", (Class[]) null);
              System.out.println("method signature: "
                      + getSignatureAttribute(meth));
  
              Field field;
              field = MemberClass.class.getField("mWha");
              System.out.println("field signature: "
                      + getSignatureAttribute(field));
          } catch (NoSuchMethodException nsme) {
              System.err.println("FAILED: " + nsme);
          } catch (NoSuchFieldException nsfe) {
              System.err.println("FAILED: " + nsfe);
          } catch (RuntimeException re) {
              System.err.println("FAILED: " + re);
              re.printStackTrace();
          }
  
          test_isAssignableFrom();
          test_isInstance();
      }
  
      private static void test_isAssignableFrom() {
          // Can always assign to things of the same type.
          assertTrue(String.class.isAssignableFrom(String.class));
  
          // Can assign any reference to java.lang.Object.
          assertTrue(Object.class.isAssignableFrom(Object.class));
          assertTrue(Object.class.isAssignableFrom(Class.class));
          assertTrue(Object.class.isAssignableFrom(String.class));
          assertFalse(Object.class.isAssignableFrom(int.class));
          assertFalse(Object.class.isAssignableFrom(long.class));
  
          // Interfaces.
          assertTrue(CharSequence.class.isAssignableFrom(String.class));
          assertFalse(CharSequence.class.isAssignableFrom(Object.class));
  
          // Superclasses.
          assertTrue(AccessibleObject.class.isAssignableFrom(Method.class));
          assertFalse(Method.class.isAssignableFrom(AccessibleObject.class));
  
          // Arrays.
          assertTrue(int[].class.isAssignableFrom(int[].class));
          assertFalse(int[].class.isAssignableFrom(char[].class));
          assertFalse(char[].class.isAssignableFrom(int[].class));
          assertTrue(Object.class.isAssignableFrom(int[].class));
          assertFalse(int[].class.isAssignableFrom(Object.class));
  
          try {
              assertFalse(Object.class.isAssignableFrom(null));
              fail();
          } catch (NullPointerException expected) {
          }
      }
  
      private static void test_isInstance() {
          // Can always assign to things of the same type.
          assertTrue(String.class.isInstance("hello"));
  
          // Can assign any reference to java.lang.Object.
          assertTrue(Object.class.isInstance(new Object()));
          assertTrue(Object.class.isInstance(Class.class));
          assertTrue(Object.class.isInstance("hello"));
  
          // Interfaces.
          assertTrue(CharSequence.class.isInstance("hello"));
          assertFalse(CharSequence.class.isInstance(new Object()));
  
          // Superclasses.
          assertTrue(AccessibleObject.class.isInstance(Method.class.getDeclaredMethods()[0]));
          assertFalse(Method.class.isInstance(Method.class.getDeclaredFields()[0]));
  
          // Arrays.
          assertTrue(int[].class.isInstance(new int[0]));
          assertFalse(int[].class.isInstance(new char[0]));
          assertFalse(char[].class.isInstance(new int[0]));
          assertTrue(Object.class.isInstance(new int[0]));
          assertFalse(int[].class.isInstance(new Object()));
  
          assertFalse(Object.class.isInstance(null));
      }
  
      private static void assertTrue(boolean b) {
          if (!b) throw new RuntimeException();
      }
  
      private static void assertFalse(boolean b) {
          if (b) throw new RuntimeException();
      }
  
      private static void fail() {
          throw new RuntimeException();
      }
  
      /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
      public static String getSignatureAttribute(Object obj) {
          Method method;
          try {
              Class c = obj.getClass();
              if (c == Method.class || c == Constructor.class) {
                c = AbstractMethod.class;
              }
              method = c.getDeclaredMethod("getSignatureAttribute");
              method.setAccessible(true);
          } catch (Exception ex) {
              ex.printStackTrace();
              return "<unknown>";
          }
  
          try {
              return (String) method.invoke(obj);
          } catch (IllegalAccessException ex) {
              throw new RuntimeException(ex);
          } catch (InvocationTargetException ex) {
              throw new RuntimeException(ex);
          }
      }
  
      /* for reflection testing */
      static class MemberClass<XYZ> {
          public MemberClass<XYZ> mWha;
  
          public MemberClass(MemberClass<XYZ> memb) {
              mWha = memb;
          }
  
          public Class<XYZ> foo() throws NoSuchMethodException {
              return null;
          }
      }
  
      /* for reflection testing (getClasses vs getDeclaredClasses) */
      static public class PublicMemberClass {
          float mBlah;
      }
  
      /*
       * Dump a variety of class attributes.
       */
      public static void printClassAttrs(Class clazz) {
          Class clazz2;
  
          System.out.println("***** " + clazz + ":");
  
          System.out.println("  name: "
              + clazz.getName());
          System.out.println("  canonical: "
              + clazz.getCanonicalName());
          System.out.println("  simple: "
              + clazz.getSimpleName());
          System.out.println("  genericSignature: "
              + getSignatureAttribute(clazz));
  
          System.out.println("  super: "
              + clazz.getSuperclass());
          System.out.println("  genericSuperclass: "
              + clazz.getGenericSuperclass());
          System.out.println("  declaring: "
              + clazz.getDeclaringClass());
          System.out.println("  enclosing: "
              + clazz.getEnclosingClass());
          System.out.println("  enclosingCon: "
              + clazz.getEnclosingConstructor());
          System.out.println("  enclosingMeth: "
              + clazz.getEnclosingMethod());
          System.out.println("  modifiers: "
              + clazz.getModifiers());
          System.out.println("  package: "
              + clazz.getPackage());
  
          System.out.println("  declaredClasses: "
              + stringifyTypeArray(clazz.getDeclaredClasses()));
          System.out.println("  member classes: "
              + stringifyTypeArray(clazz.getClasses()));
  
          System.out.println("  isAnnotation: "
              + clazz.isAnnotation());
          System.out.println("  isAnonymous: "
              + clazz.isAnonymousClass());
          System.out.println("  isArray: "
              + clazz.isArray());
          System.out.println("  isEnum: "
              + clazz.isEnum());
          System.out.println("  isInterface: "
              + clazz.isInterface());
          System.out.println("  isLocalClass: "
              + clazz.isLocalClass());
          System.out.println("  isMemberClass: "
              + clazz.isMemberClass());
          System.out.println("  isPrimitive: "
              + clazz.isPrimitive());
          System.out.println("  isSynthetic: "
              + clazz.isSynthetic());
  
          System.out.println("  genericInterfaces: "
              + stringifyTypeArray(clazz.getGenericInterfaces()));
  
          TypeVariable<Class<?>>[] typeParameters = clazz.getTypeParameters();
          System.out.println("  typeParameters: "
              + stringifyTypeArray(typeParameters));
      }
  
      /*
       * Convert an array of Type into a string.  Start with an array count.
       */
      private static String stringifyTypeArray(Type[] types) {
          List<String> typeStringList = new ArrayList<String>();
          for (Type t : types) {
            typeStringList.add(t.toString());
          }
          // Sort types alphabetically so they're always printed in the same order.
          // For instance, Class.getClasses() does not guarantee any order for the
          // returned Class[].
          Collections.sort(typeStringList);
  
          StringBuilder stb = new StringBuilder();
          boolean first = true;
  
          stb.append("[" + types.length + "]");
  
          for (String typeString : typeStringList) {
              if (first) {
                  stb.append(" ");
                  first = false;
              } else {
                  stb.append(", ");
              }
              stb.append(typeString);
          }
  
          return stb.toString();
      }
  }
  