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 {
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 
showModifiers(Class<?> c)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
test56267()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 
main()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 
test_isAssignableFrom()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 
test_isInstance()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 
assertTrue(boolean b)213     private static void assertTrue(boolean b) {
214         if (!b) throw new RuntimeException();
215     }
216 
assertFalse(boolean b)217     private static void assertFalse(boolean b) {
218         if (b) throw new RuntimeException();
219     }
220 
fail()221     private static void fail() {
222         throw new RuntimeException();
223     }
224 
225     /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
getSignatureAttribute(Object obj)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 
MemberClass(MemberClass<XYZ> memb)253         public MemberClass(MemberClass<XYZ> memb) {
254             mWha = memb;
255         }
256 
foo()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      */
printClassAttrs(Class<T> clazz)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      */
stringifyTypeArray(Type[] types)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