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