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 
    111         /* anonymous, not local, not member */
    112         printClassAttrs((new OtherClass() { int i = 5; }).getClass());
    113 
    114         /* member, not anonymous, not local */
    115         printClassAttrs(MemberClass.class);
    116 
    117         /* fancy */
    118         printClassAttrs(FancyClass.class);
    119 
    120         try {
    121             Constructor<?> cons;
    122             cons = MemberClass.class.getConstructor(MemberClass.class);
    123             System.out.println("constructor signature: "
    124                     + getSignatureAttribute(cons));
    125 
    126             Method meth;
    127             meth = MemberClass.class.getMethod("foo");
    128             System.out.println("method signature: "
    129                     + getSignatureAttribute(meth));
    130 
    131             Field field;
    132             field = MemberClass.class.getField("mWha");
    133             System.out.println("field signature: "
    134                     + getSignatureAttribute(field));
    135         } catch (NoSuchMethodException nsme) {
    136             System.err.println("FAILED: " + nsme);
    137         } catch (NoSuchFieldException nsfe) {
    138             System.err.println("FAILED: " + nsfe);
    139         } catch (RuntimeException re) {
    140             System.err.println("FAILED: " + re);
    141             re.printStackTrace();
    142         }
    143 
    144         test_isAssignableFrom();
    145         test_isInstance();
    146     }
    147 
    148     private static void test_isAssignableFrom() {
    149         // Can always assign to things of the same type.
    150         assertTrue(String.class.isAssignableFrom(String.class));
    151 
    152         // Can assign any reference to java.lang.Object.
    153         assertTrue(Object.class.isAssignableFrom(Object.class));
    154         assertTrue(Object.class.isAssignableFrom(Class.class));
    155         assertTrue(Object.class.isAssignableFrom(String.class));
    156         assertFalse(Object.class.isAssignableFrom(int.class));
    157         assertFalse(Object.class.isAssignableFrom(long.class));
    158 
    159         // Interfaces.
    160         assertTrue(CharSequence.class.isAssignableFrom(String.class));
    161         assertFalse(CharSequence.class.isAssignableFrom(Object.class));
    162 
    163         // Superclasses.
    164         assertTrue(AccessibleObject.class.isAssignableFrom(Method.class));
    165         assertFalse(Method.class.isAssignableFrom(AccessibleObject.class));
    166 
    167         // Arrays.
    168         assertTrue(int[].class.isAssignableFrom(int[].class));
    169         assertFalse(int[].class.isAssignableFrom(char[].class));
    170         assertFalse(char[].class.isAssignableFrom(int[].class));
    171         assertTrue(Object.class.isAssignableFrom(int[].class));
    172         assertFalse(int[].class.isAssignableFrom(Object.class));
    173 
    174         try {
    175             assertFalse(Object.class.isAssignableFrom(null));
    176             fail();
    177         } catch (NullPointerException expected) {
    178         }
    179     }
    180 
    181     private static void test_isInstance() {
    182         // Can always assign to things of the same type.
    183         assertTrue(String.class.isInstance("hello"));
    184 
    185         // Can assign any reference to java.lang.Object.
    186         assertTrue(Object.class.isInstance(new Object()));
    187         assertTrue(Object.class.isInstance(Class.class));
    188         assertTrue(Object.class.isInstance("hello"));
    189 
    190         // Interfaces.
    191         assertTrue(CharSequence.class.isInstance("hello"));
    192         assertFalse(CharSequence.class.isInstance(new Object()));
    193 
    194         // Superclasses.
    195         assertTrue(AccessibleObject.class.isInstance(Method.class.getDeclaredMethods()[0]));
    196         assertFalse(Method.class.isInstance(Method.class.getDeclaredFields()[0]));
    197 
    198         // Arrays.
    199         assertTrue(int[].class.isInstance(new int[0]));
    200         assertFalse(int[].class.isInstance(new char[0]));
    201         assertFalse(char[].class.isInstance(new int[0]));
    202         assertTrue(Object.class.isInstance(new int[0]));
    203         assertFalse(int[].class.isInstance(new Object()));
    204 
    205         assertFalse(Object.class.isInstance(null));
    206     }
    207 
    208     private static void assertTrue(boolean b) {
    209         if (!b) throw new RuntimeException();
    210     }
    211 
    212     private static void assertFalse(boolean b) {
    213         if (b) throw new RuntimeException();
    214     }
    215 
    216     private static void fail() {
    217         throw new RuntimeException();
    218     }
    219 
    220     /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
    221     public static String getSignatureAttribute(Object obj) {
    222         Method method;
    223         try {
    224             Class<?> c = obj.getClass();
    225             if (c == Method.class || c == Constructor.class) {
    226               c = Executable.class;
    227             }
    228             method = c.getDeclaredMethod("getSignatureAttribute");
    229             method.setAccessible(true);
    230         } catch (Exception ex) {
    231             ex.printStackTrace();
    232             return "<unknown>";
    233         }
    234 
    235         try {
    236             return (String) method.invoke(obj);
    237         } catch (IllegalAccessException ex) {
    238             throw new RuntimeException(ex);
    239         } catch (InvocationTargetException ex) {
    240             throw new RuntimeException(ex);
    241         }
    242     }
    243 
    244     /* for reflection testing */
    245     static class MemberClass<XYZ> {
    246         public MemberClass<XYZ> mWha;
    247 
    248         public MemberClass(MemberClass<XYZ> memb) {
    249             mWha = memb;
    250         }
    251 
    252         public Class<XYZ> foo() throws NoSuchMethodException {
    253             return null;
    254         }
    255     }
    256 
    257     /* for reflection testing (getClasses vs getDeclaredClasses) */
    258     static public class PublicMemberClass {
    259         float mBlah;
    260     }
    261 
    262     /*
    263      * Dump a variety of class attributes.
    264      */
    265     public static <T> void printClassAttrs(Class<T> clazz) {
    266         System.out.println("***** " + clazz + ":");
    267 
    268         System.out.println("  name: "
    269             + clazz.getName());
    270         System.out.println("  canonical: "
    271             + clazz.getCanonicalName());
    272         System.out.println("  simple: "
    273             + clazz.getSimpleName());
    274         System.out.println("  genericSignature: "
    275             + getSignatureAttribute(clazz));
    276 
    277         System.out.println("  super: "
    278             + clazz.getSuperclass());
    279         System.out.println("  genericSuperclass: "
    280             + clazz.getGenericSuperclass());
    281         System.out.println("  declaring: "
    282             + clazz.getDeclaringClass());
    283         System.out.println("  enclosing: "
    284             + clazz.getEnclosingClass());
    285         System.out.println("  enclosingCon: "
    286             + clazz.getEnclosingConstructor());
    287         System.out.println("  enclosingMeth: "
    288             + clazz.getEnclosingMethod());
    289         System.out.println("  modifiers: "
    290             + clazz.getModifiers());
    291         System.out.println("  package: "
    292             + clazz.getPackage());
    293 
    294         System.out.println("  declaredClasses: "
    295             + stringifyTypeArray(clazz.getDeclaredClasses()));
    296         System.out.println("  member classes: "
    297             + stringifyTypeArray(clazz.getClasses()));
    298 
    299         System.out.println("  isAnnotation: "
    300             + clazz.isAnnotation());
    301         System.out.println("  isAnonymous: "
    302             + clazz.isAnonymousClass());
    303         System.out.println("  isArray: "
    304             + clazz.isArray());
    305         System.out.println("  isEnum: "
    306             + clazz.isEnum());
    307         System.out.println("  isInterface: "
    308             + clazz.isInterface());
    309         System.out.println("  isLocalClass: "
    310             + clazz.isLocalClass());
    311         System.out.println("  isMemberClass: "
    312             + clazz.isMemberClass());
    313         System.out.println("  isPrimitive: "
    314             + clazz.isPrimitive());
    315         System.out.println("  isSynthetic: "
    316             + clazz.isSynthetic());
    317 
    318         System.out.println("  genericInterfaces: "
    319             + stringifyTypeArray(clazz.getGenericInterfaces()));
    320 
    321         TypeVariable<Class<T>>[] typeParameters = clazz.getTypeParameters();
    322         System.out.println("  typeParameters: "
    323             + stringifyTypeArray(typeParameters));
    324     }
    325 
    326     /*
    327      * Convert an array of Type into a string.  Start with an array count.
    328      */
    329     private static String stringifyTypeArray(Type[] types) {
    330         List<String> typeStringList = new ArrayList<String>();
    331         for (Type t : types) {
    332           typeStringList.add(t.toString());
    333         }
    334         // Sort types alphabetically so they're always printed in the same order.
    335         // For instance, Class.getClasses() does not guarantee any order for the
    336         // returned Class[].
    337         Collections.sort(typeStringList);
    338 
    339         StringBuilder stb = new StringBuilder();
    340         boolean first = true;
    341 
    342         stb.append("[" + types.length + "]");
    343 
    344         for (String typeString : typeStringList) {
    345             if (first) {
    346                 stb.append(" ");
    347                 first = false;
    348             } else {
    349                 stb.append(", ");
    350             }
    351             stb.append(typeString);
    352         }
    353 
    354         return stb.toString();
    355     }
    356 }
    357