blob: c2e41c5b3e0d1ccbc6e05bfa953b05786effc23f [file] [log] [blame]
jeffhao5d1ac922011-09-29 17:41:15 -07001import otherpackage.OtherPackageClass;
2
Elliott Hughes00626c22013-06-14 15:04:14 -07003import java.io.Serializable;
jeffhao5d1ac922011-09-29 17:41:15 -07004import java.lang.reflect.AccessibleObject;
5import java.lang.reflect.Constructor;
6import java.lang.reflect.Field;
7import java.lang.reflect.InvocationTargetException;
8import java.lang.reflect.Method;
Elliott Hughes00626c22013-06-14 15:04:14 -07009import java.lang.reflect.Modifier;
jeffhao5d1ac922011-09-29 17:41:15 -070010import java.lang.reflect.Type;
Elliott Hughes741b5b72012-01-31 19:18:51 -080011import java.lang.reflect.TypeVariable;
Sebastien Hertzb1add752015-03-04 16:45:31 +010012import java.util.ArrayList;
13import java.util.Collections;
14import java.util.List;
jeffhao5d1ac922011-09-29 17:41:15 -070015
16public class 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
Elliott Hughes00626c22013-06-14 15:04:14 -070029 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
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
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
jeffhao5d1ac922011-09-29 17:41:15 -070092 public static void main() {
Elliott Hughes00626c22013-06-14 15:04:14 -070093 test56267();
94
jeffhao5d1ac922011-09-29 17:41:15 -070095 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
Elliott Hughes741b5b72012-01-31 19:18:51 -0800116 /* fancy */
117 printClassAttrs(FancyClass.class);
118
jeffhao5d1ac922011-09-29 17:41:15 -0700119 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 }
Elliott Hughesc1503432012-03-30 17:24:47 -0700143
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();
jeffhao5d1ac922011-09-29 17:41:15 -0700218 }
219
220 /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
221 public static String getSignatureAttribute(Object obj) {
222 Method method;
223 try {
Elliott Hughes32caed42011-10-06 13:41:44 -0700224 Class c = Class.forName("libcore.reflect.AnnotationAccess");
225 method = c.getDeclaredMethod("getSignature", java.lang.reflect.AnnotatedElement.class);
jeffhao5d1ac922011-09-29 17:41:15 -0700226 method.setAccessible(true);
Elliott Hughes32caed42011-10-06 13:41:44 -0700227 } catch (Exception ex) {
jeffhao5d1ac922011-09-29 17:41:15 -0700228 ex.printStackTrace();
229 return "<unknown>";
230 }
231
232 try {
Elliott Hughes32caed42011-10-06 13:41:44 -0700233 return (String) method.invoke(null, obj);
jeffhao5d1ac922011-09-29 17:41:15 -0700234 } 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
245 public MemberClass(MemberClass<XYZ> memb) {
246 mWha = memb;
247 }
248
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 */
262 public static void printClassAttrs(Class clazz) {
jeffhao5d1ac922011-09-29 17:41:15 -0700263 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());
Elliott Hughes741b5b72012-01-31 19:18:51 -0800278 System.out.println(" genericSuperclass: "
jeffhao5d1ac922011-09-29 17:41:15 -0700279 + 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
Elliott Hughes741b5b72012-01-31 19:18:51 -0800317 System.out.println(" genericInterfaces: "
jeffhao5d1ac922011-09-29 17:41:15 -0700318 + stringifyTypeArray(clazz.getGenericInterfaces()));
Elliott Hughes741b5b72012-01-31 19:18:51 -0800319
320 TypeVariable<Class<?>>[] typeParameters = clazz.getTypeParameters();
321 System.out.println(" typeParameters: "
322 + stringifyTypeArray(typeParameters));
jeffhao5d1ac922011-09-29 17:41:15 -0700323 }
324
325 /*
326 * Convert an array of Type into a string. Start with an array count.
327 */
328 private static String stringifyTypeArray(Type[] types) {
Sebastien Hertzb1add752015-03-04 16:45:31 +0100329 List<String> typeStringList = new ArrayList<String>();
330 for (Type t : types) {
331 typeStringList.add(t.toString());
332 }
Sebastien Hertzc5e3ab22015-03-04 19:03:48 +0100333 // 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[].
Sebastien Hertzb1add752015-03-04 16:45:31 +0100336 Collections.sort(typeStringList);
337
jeffhao5d1ac922011-09-29 17:41:15 -0700338 StringBuilder stb = new StringBuilder();
339 boolean first = true;
340
341 stb.append("[" + types.length + "]");
342
Sebastien Hertzb1add752015-03-04 16:45:31 +0100343 for (String typeString : typeStringList) {
jeffhao5d1ac922011-09-29 17:41:15 -0700344 if (first) {
345 stb.append(" ");
346 first = false;
347 } else {
348 stb.append(", ");
349 }
Sebastien Hertzb1add752015-03-04 16:45:31 +0100350 stb.append(typeString);
jeffhao5d1ac922011-09-29 17:41:15 -0700351 }
352
353 return stb.toString();
354 }
355}