Home | History | Annotate | Download | only in src
      1 import otherpackage.OtherPackageClass;
      2 
      3 import java.io.Serializable;
      4 import java.lang.reflect.AccessibleObject;
      5 import java.lang.reflect.Constructor;
      6 import java.lang.reflect.Executable;
      7 import java.lang.reflect.Field;
      8 import java.lang.reflect.InvocationTargetException;
      9 import java.lang.reflect.Method;
     10 import java.lang.reflect.Modifier;
     11 import java.lang.reflect.Type;
     12 import java.lang.reflect.TypeVariable;
     13 import java.util.ArrayList;
     14 import java.util.Collections;
     15 import java.util.List;
     16 
     17 public class ClassAttrs {
     18     ClassAttrs() {
     19         /* local, not anonymous, not member */
     20         class ConsInnerNamed {
     21             public void showMe() {
     22                 printClassAttrs(this.getClass());
     23             }
     24         }
     25 
     26         ConsInnerNamed cinner = new ConsInnerNamed();
     27         cinner.showMe();
     28     }
     29 
     30     public class PublicInnerClass {
     31     }
     32 
     33     protected class ProtectedInnerClass {
     34     }
     35 
     36     private class PrivateInnerClass {
     37     }
     38 
     39     class PackagePrivateInnerClass {
     40     }
     41 
     42     public interface PublicInnerInterface {
     43     }
     44 
     45     protected interface ProtectedInnerInterface {
     46     }
     47 
     48     private interface PrivateInnerInterface {
     49     }
     50 
     51     interface PackagePrivateInnerInterface {
     52     }
     53 
     54     private static void showModifiers(Class<?> c) {
     55         System.out.println(Modifier.toString(c.getModifiers()) + " " + c.getName());
     56     }
     57 
     58     // https://code.google.com/p/android/issues/detail?id=56267
     59     private static void test56267() {
     60         // Primitive classes.
     61         showModifiers(int.class);
     62         showModifiers(int[].class);
     63 
     64         // Regular classes.
     65         showModifiers(Object.class);
     66         showModifiers(Object[].class);
     67 
     68         // Inner classes.
     69         showModifiers(PublicInnerClass.class);
     70         showModifiers(PublicInnerClass[].class);
     71         showModifiers(ProtectedInnerClass.class);
     72         showModifiers(ProtectedInnerClass[].class);
     73         showModifiers(PrivateInnerClass.class);
     74         showModifiers(PrivateInnerClass[].class);
     75         showModifiers(PackagePrivateInnerClass.class);
     76         showModifiers(PackagePrivateInnerClass[].class);
     77 
     78         // Regular interfaces.
     79         showModifiers(Serializable.class);
     80         showModifiers(Serializable[].class);
     81 
     82         // Inner interfaces.
     83         showModifiers(PublicInnerInterface.class);
     84         showModifiers(PublicInnerInterface[].class);
     85         showModifiers(ProtectedInnerInterface.class);
     86         showModifiers(ProtectedInnerInterface[].class);
     87         showModifiers(PrivateInnerInterface.class);
     88         showModifiers(PrivateInnerInterface[].class);
     89         showModifiers(PackagePrivateInnerInterface.class);
     90         showModifiers(PackagePrivateInnerInterface[].class);
     91     }
     92 
     93     public static void main() {
     94         test56267();
     95 
     96         printClassAttrs(ClassAttrs.class);
     97         printClassAttrs(OtherClass.class);
     98         printClassAttrs(OtherPackageClass.class);
     99 
    100         /* local, not anonymous, not member */
    101         class InnerNamed {
    102             public void showMe() {
    103                 printClassAttrs(this.getClass());
    104             }
    105         }
    106         InnerNamed inner = new InnerNamed();
    107         inner.showMe();
    108 
    109         ClassAttrs attrs = new ClassAttrs();
    110         try {
    111             /* anonymous, not local, not member */
    112             printClassAttrs(Class.forName("ClassAttrs$1")); // ClassAttrs$1.j
    113         } catch (ClassNotFoundException e) {
    114             System.out.println("FAILED: " + e);
    115             e.printStackTrace(System.out);
    116             throw new AssertionError(e);
    117         }
    118 
    119         /* member, not anonymous, not local */
    120         printClassAttrs(MemberClass.class);
    121 
    122         /* fancy */
    123         printClassAttrs(FancyClass.class);
    124 
    125         try {
    126             Constructor<?> cons;
    127             cons = MemberClass.class.getConstructor(MemberClass.class);
    128             System.out.println("constructor signature: "
    129                     + getSignatureAttribute(cons));
    130 
    131             Method meth;
    132             meth = MemberClass.class.getMethod("foo");
    133             System.out.println("method signature: "
    134                     + getSignatureAttribute(meth));
    135 
    136             Field field;
    137             field = MemberClass.class.getField("mWha");
    138             System.out.println("field signature: "
    139                     + getSignatureAttribute(field));
    140         } catch (NoSuchMethodException nsme) {
    141             System.out.println("FAILED: " + nsme);
    142         } catch (NoSuchFieldException nsfe) {
    143             System.out.println("FAILED: " + nsfe);
    144         } catch (RuntimeException re) {
    145             System.out.println("FAILED: " + re);
    146             re.printStackTrace(System.out);
    147         }
    148 
    149         test_isAssignableFrom();
    150         test_isInstance();
    151     }
    152 
    153     private static void test_isAssignableFrom() {
    154         // Can always assign to things of the same type.
    155         assertTrue(String.class.isAssignableFrom(String.class));
    156 
    157         // Can assign any reference to java.lang.Object.
    158         assertTrue(Object.class.isAssignableFrom(Object.class));
    159         assertTrue(Object.class.isAssignableFrom(Class.class));
    160         assertTrue(Object.class.isAssignableFrom(String.class));
    161         assertFalse(Object.class.isAssignableFrom(int.class));
    162         assertFalse(Object.class.isAssignableFrom(long.class));
    163 
    164         // Interfaces.
    165         assertTrue(CharSequence.class.isAssignableFrom(String.class));
    166         assertFalse(CharSequence.class.isAssignableFrom(Object.class));
    167 
    168         // Superclasses.
    169         assertTrue(AccessibleObject.class.isAssignableFrom(Method.class));
    170         assertFalse(Method.class.isAssignableFrom(AccessibleObject.class));
    171 
    172         // Arrays.
    173         assertTrue(int[].class.isAssignableFrom(int[].class));
    174         assertFalse(int[].class.isAssignableFrom(char[].class));
    175         assertFalse(char[].class.isAssignableFrom(int[].class));
    176         assertTrue(Object.class.isAssignableFrom(int[].class));
    177         assertFalse(int[].class.isAssignableFrom(Object.class));
    178 
    179         try {
    180             assertFalse(Object.class.isAssignableFrom(null));
    181             fail();
    182         } catch (NullPointerException expected) {
    183         }
    184     }
    185 
    186     private static void test_isInstance() {
    187         // Can always assign to things of the same type.
    188         assertTrue(String.class.isInstance("hello"));
    189 
    190         // Can assign any reference to java.lang.Object.
    191         assertTrue(Object.class.isInstance(new Object()));
    192         assertTrue(Object.class.isInstance(Class.class));
    193         assertTrue(Object.class.isInstance("hello"));
    194 
    195         // Interfaces.
    196         assertTrue(CharSequence.class.isInstance("hello"));
    197         assertFalse(CharSequence.class.isInstance(new Object()));
    198 
    199         // Superclasses.
    200         assertTrue(AccessibleObject.class.isInstance(Method.class.getDeclaredMethods()[0]));
    201         assertFalse(Method.class.isInstance(Method.class.getDeclaredFields()[0]));
    202 
    203         // Arrays.
    204         assertTrue(int[].class.isInstance(new int[0]));
    205         assertFalse(int[].class.isInstance(new char[0]));
    206         assertFalse(char[].class.isInstance(new int[0]));
    207         assertTrue(Object.class.isInstance(new int[0]));
    208         assertFalse(int[].class.isInstance(new Object()));
    209 
    210         assertFalse(Object.class.isInstance(null));
    211     }
    212 
    213     private static void assertTrue(boolean b) {
    214         if (!b) throw new RuntimeException();
    215     }
    216 
    217     private static void assertFalse(boolean b) {
    218         if (b) throw new RuntimeException();
    219     }
    220 
    221     private static void fail() {
    222         throw new RuntimeException();
    223     }
    224 
    225     /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
    226     public static String getSignatureAttribute(Object obj) {
    227         Method method;
    228         try {
    229             Class<?> c = obj.getClass();
    230             if (c == Method.class || c == Constructor.class) {
    231               c = Executable.class;
    232             }
    233             method = c.getDeclaredMethod("getSignatureAttribute");
    234             method.setAccessible(true);
    235         } catch (Exception ex) {
    236             ex.printStackTrace(System.out);
    237             return "<unknown>";
    238         }
    239 
    240         try {
    241             return (String) method.invoke(obj);
    242         } catch (IllegalAccessException ex) {
    243             throw new RuntimeException(ex);
    244         } catch (InvocationTargetException ex) {
    245             throw new RuntimeException(ex);
    246         }
    247     }
    248 
    249     /* for reflection testing */
    250     static class MemberClass<XYZ> {
    251         public MemberClass<XYZ> mWha;
    252 
    253         public MemberClass(MemberClass<XYZ> memb) {
    254             mWha = memb;
    255         }
    256 
    257         public Class<XYZ> foo() throws NoSuchMethodException {
    258             return null;
    259         }
    260     }
    261 
    262     /* for reflection testing (getClasses vs getDeclaredClasses) */
    263     static public class PublicMemberClass {
    264         float mBlah;
    265     }
    266 
    267     /*
    268      * Dump a variety of class attributes.
    269      */
    270     public static <T> void printClassAttrs(Class<T> clazz) {
    271         System.out.println("***** " + clazz + ":");
    272 
    273         System.out.println("  name: "
    274             + clazz.getName());
    275         System.out.println("  canonical: "
    276             + clazz.getCanonicalName());
    277         System.out.println("  simple: "
    278             + clazz.getSimpleName());
    279         System.out.println("  genericSignature: "
    280             + getSignatureAttribute(clazz));
    281 
    282         System.out.println("  super: "
    283             + clazz.getSuperclass());
    284         System.out.println("  genericSuperclass: "
    285             + clazz.getGenericSuperclass());
    286         System.out.println("  declaring: "
    287             + clazz.getDeclaringClass());
    288         System.out.println("  enclosing: "
    289             + clazz.getEnclosingClass());
    290         System.out.println("  enclosingCon: "
    291             + clazz.getEnclosingConstructor());
    292         System.out.println("  enclosingMeth: "
    293             + clazz.getEnclosingMethod());
    294         System.out.println("  modifiers: "
    295             + clazz.getModifiers());
    296         System.out.println("  package: "
    297             + clazz.getPackage());
    298 
    299         System.out.println("  declaredClasses: "
    300             + stringifyTypeArray(clazz.getDeclaredClasses()));
    301         System.out.println("  member classes: "
    302             + stringifyTypeArray(clazz.getClasses()));
    303 
    304         System.out.println("  isAnnotation: "
    305             + clazz.isAnnotation());
    306         System.out.println("  isAnonymous: "
    307             + clazz.isAnonymousClass());
    308         System.out.println("  isArray: "
    309             + clazz.isArray());
    310         System.out.println("  isEnum: "
    311             + clazz.isEnum());
    312         System.out.println("  isInterface: "
    313             + clazz.isInterface());
    314         System.out.println("  isLocalClass: "
    315             + clazz.isLocalClass());
    316         System.out.println("  isMemberClass: "
    317             + clazz.isMemberClass());
    318         System.out.println("  isPrimitive: "
    319             + clazz.isPrimitive());
    320         System.out.println("  isSynthetic: "
    321             + clazz.isSynthetic());
    322 
    323         System.out.println("  genericInterfaces: "
    324             + stringifyTypeArray(clazz.getGenericInterfaces()));
    325 
    326         TypeVariable<Class<T>>[] typeParameters = clazz.getTypeParameters();
    327         System.out.println("  typeParameters: "
    328             + stringifyTypeArray(typeParameters));
    329     }
    330 
    331     /*
    332      * Convert an array of Type into a string.  Start with an array count.
    333      */
    334     private static String stringifyTypeArray(Type[] types) {
    335         List<String> typeStringList = new ArrayList<String>();
    336         for (Type t : types) {
    337           typeStringList.add(t.toString());
    338         }
    339         // Sort types alphabetically so they're always printed in the same order.
    340         // For instance, Class.getClasses() does not guarantee any order for the
    341         // returned Class[].
    342         Collections.sort(typeStringList);
    343 
    344         StringBuilder stb = new StringBuilder();
    345         boolean first = true;
    346 
    347         stb.append("[" + types.length + "]");
    348 
    349         for (String typeString : typeStringList) {
    350             if (first) {
    351                 stb.append(" ");
    352                 first = false;
    353             } else {
    354                 stb.append(", ");
    355             }
    356             stb.append(typeString);
    357         }
    358 
    359         return stb.toString();
    360     }
    361 }
    362