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 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 
16 public class ClassAttrs {
ClassAttrs()17     ClassAttrs() {
18         /* local, not anonymous, not member */
19         class ConsInnerNamed {
20             public void showMe() {
21                 printClassAttrs(this.getClass());
22             }
23         }
24 
25         ConsInnerNamed cinner = new ConsInnerNamed();
26         cinner.showMe();
27     }
28 
29     public class PublicInnerClass {
30     }
31 
32     protected class ProtectedInnerClass {
33     }
34 
35     private class PrivateInnerClass {
36     }
37 
38     class PackagePrivateInnerClass {
39     }
40 
41     public interface PublicInnerInterface {
42     }
43 
44     protected interface ProtectedInnerInterface {
45     }
46 
47     private interface PrivateInnerInterface {
48     }
49 
50     interface PackagePrivateInnerInterface {
51     }
52 
showModifiers(Class<?> c)53     private static void showModifiers(Class<?> c) {
54         System.out.println(Modifier.toString(c.getModifiers()) + " " + c.getName());
55     }
56 
57     // https://code.google.com/p/android/issues/detail?id=56267
test56267()58     private static void test56267() {
59         // Primitive classes.
60         showModifiers(int.class);
61         showModifiers(int[].class);
62 
63         // Regular classes.
64         showModifiers(Object.class);
65         showModifiers(Object[].class);
66 
67         // Inner classes.
68         showModifiers(PublicInnerClass.class);
69         showModifiers(PublicInnerClass[].class);
70         showModifiers(ProtectedInnerClass.class);
71         showModifiers(ProtectedInnerClass[].class);
72         showModifiers(PrivateInnerClass.class);
73         showModifiers(PrivateInnerClass[].class);
74         showModifiers(PackagePrivateInnerClass.class);
75         showModifiers(PackagePrivateInnerClass[].class);
76 
77         // Regular interfaces.
78         showModifiers(Serializable.class);
79         showModifiers(Serializable[].class);
80 
81         // Inner interfaces.
82         showModifiers(PublicInnerInterface.class);
83         showModifiers(PublicInnerInterface[].class);
84         showModifiers(ProtectedInnerInterface.class);
85         showModifiers(ProtectedInnerInterface[].class);
86         showModifiers(PrivateInnerInterface.class);
87         showModifiers(PrivateInnerInterface[].class);
88         showModifiers(PackagePrivateInnerInterface.class);
89         showModifiers(PackagePrivateInnerInterface[].class);
90     }
91 
main()92     public static void main() {
93         test56267();
94 
95         printClassAttrs(ClassAttrs.class);
96         printClassAttrs(OtherClass.class);
97         printClassAttrs(OtherPackageClass.class);
98 
99         /* local, not anonymous, not member */
100         class InnerNamed {
101             public void showMe() {
102                 printClassAttrs(this.getClass());
103             }
104         }
105         InnerNamed inner = new InnerNamed();
106         inner.showMe();
107 
108         ClassAttrs attrs = new ClassAttrs();
109 
110         /* anonymous, not local, not member */
111         printClassAttrs((new OtherClass() { int i = 5; }).getClass());
112 
113         /* member, not anonymous, not local */
114         printClassAttrs(MemberClass.class);
115 
116         /* fancy */
117         printClassAttrs(FancyClass.class);
118 
119         try {
120             Constructor cons;
121             cons = MemberClass.class.getConstructor(
122                     new Class[] { MemberClass.class });
123             System.out.println("constructor signature: "
124                     + getSignatureAttribute(cons));
125 
126             Method meth;
127             meth = MemberClass.class.getMethod("foo", (Class[]) null);
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 
test_isAssignableFrom()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 
test_isInstance()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 
assertTrue(boolean b)208     private static void assertTrue(boolean b) {
209         if (!b) throw new RuntimeException();
210     }
211 
assertFalse(boolean b)212     private static void assertFalse(boolean b) {
213         if (b) throw new RuntimeException();
214     }
215 
fail()216     private static void fail() {
217         throw new RuntimeException();
218     }
219 
220     /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
getSignatureAttribute(Object obj)221     public static String getSignatureAttribute(Object obj) {
222         Method method;
223         try {
224             Class c = Class.forName("libcore.reflect.AnnotationAccess");
225             method = c.getDeclaredMethod("getSignature", java.lang.reflect.AnnotatedElement.class);
226             method.setAccessible(true);
227         } catch (Exception ex) {
228             ex.printStackTrace();
229             return "<unknown>";
230         }
231 
232         try {
233             return (String) method.invoke(null, obj);
234         } catch (IllegalAccessException ex) {
235             throw new RuntimeException(ex);
236         } catch (InvocationTargetException ex) {
237             throw new RuntimeException(ex);
238         }
239     }
240 
241     /* for reflection testing */
242     static class MemberClass<XYZ> {
243         public MemberClass<XYZ> mWha;
244 
MemberClass(MemberClass<XYZ> memb)245         public MemberClass(MemberClass<XYZ> memb) {
246             mWha = memb;
247         }
248 
foo()249         public Class<XYZ> foo() throws NoSuchMethodException {
250             return null;
251         }
252     }
253 
254     /* for reflection testing (getClasses vs getDeclaredClasses) */
255     static public class PublicMemberClass {
256         float mBlah;
257     }
258 
259     /*
260      * Dump a variety of class attributes.
261      */
printClassAttrs(Class clazz)262     public static void printClassAttrs(Class clazz) {
263         Class clazz2;
264 
265         System.out.println("***** " + clazz + ":");
266 
267         System.out.println("  name: "
268             + clazz.getName());
269         System.out.println("  canonical: "
270             + clazz.getCanonicalName());
271         System.out.println("  simple: "
272             + clazz.getSimpleName());
273         System.out.println("  genericSignature: "
274             + getSignatureAttribute(clazz));
275 
276         System.out.println("  super: "
277             + clazz.getSuperclass());
278         System.out.println("  genericSuperclass: "
279             + clazz.getGenericSuperclass());
280         System.out.println("  declaring: "
281             + clazz.getDeclaringClass());
282         System.out.println("  enclosing: "
283             + clazz.getEnclosingClass());
284         System.out.println("  enclosingCon: "
285             + clazz.getEnclosingConstructor());
286         System.out.println("  enclosingMeth: "
287             + clazz.getEnclosingMethod());
288         System.out.println("  modifiers: "
289             + clazz.getModifiers());
290         System.out.println("  package: "
291             + clazz.getPackage());
292 
293         System.out.println("  declaredClasses: "
294             + stringifyTypeArray(clazz.getDeclaredClasses()));
295         System.out.println("  member classes: "
296             + stringifyTypeArray(clazz.getClasses()));
297 
298         System.out.println("  isAnnotation: "
299             + clazz.isAnnotation());
300         System.out.println("  isAnonymous: "
301             + clazz.isAnonymousClass());
302         System.out.println("  isArray: "
303             + clazz.isArray());
304         System.out.println("  isEnum: "
305             + clazz.isEnum());
306         System.out.println("  isInterface: "
307             + clazz.isInterface());
308         System.out.println("  isLocalClass: "
309             + clazz.isLocalClass());
310         System.out.println("  isMemberClass: "
311             + clazz.isMemberClass());
312         System.out.println("  isPrimitive: "
313             + clazz.isPrimitive());
314         System.out.println("  isSynthetic: "
315             + clazz.isSynthetic());
316 
317         System.out.println("  genericInterfaces: "
318             + stringifyTypeArray(clazz.getGenericInterfaces()));
319 
320         TypeVariable<Class<?>>[] typeParameters = clazz.getTypeParameters();
321         System.out.println("  typeParameters: "
322             + stringifyTypeArray(typeParameters));
323     }
324 
325     /*
326      * Convert an array of Type into a string.  Start with an array count.
327      */
stringifyTypeArray(Type[] types)328     private static String stringifyTypeArray(Type[] types) {
329         List<String> typeStringList = new ArrayList<String>();
330         for (Type t : types) {
331           typeStringList.add(t.toString());
332         }
333         // Sort types alphabetically so they're always printed in the same order.
334         // For instance, Class.getClasses() does not guarantee any order for the
335         // returned Class[].
336         Collections.sort(typeStringList);
337 
338         StringBuilder stb = new StringBuilder();
339         boolean first = true;
340 
341         stb.append("[" + types.length + "]");
342 
343         for (String typeString : typeStringList) {
344             if (first) {
345                 stb.append(" ");
346                 first = false;
347             } else {
348                 stb.append(", ");
349             }
350             stb.append(typeString);
351         }
352 
353         return stb.toString();
354     }
355 }
356