blob: 38bd525b86e9e9bea4d2f08bf8c6b0d8cb039b91 [file] [log] [blame]
jeffhao5d1ac922011-09-29 17:41:15 -07001import otherpackage.OtherPackageClass;
2
Elliott Hughes00626c22013-06-14 15:04:14 -07003import java.io.Serializable;
Jeff Hao1133db72016-04-04 19:50:14 -07004import java.lang.reflect.AbstractMethod;
jeffhao5d1ac922011-09-29 17:41:15 -07005import java.lang.reflect.AccessibleObject;
6import java.lang.reflect.Constructor;
7import java.lang.reflect.Field;
8import java.lang.reflect.InvocationTargetException;
9import java.lang.reflect.Method;
Elliott Hughes00626c22013-06-14 15:04:14 -070010import java.lang.reflect.Modifier;
jeffhao5d1ac922011-09-29 17:41:15 -070011import java.lang.reflect.Type;
Elliott Hughes741b5b72012-01-31 19:18:51 -080012import java.lang.reflect.TypeVariable;
Sebastien Hertzb1add752015-03-04 16:45:31 +010013import java.util.ArrayList;
14import java.util.Collections;
15import java.util.List;
jeffhao5d1ac922011-09-29 17:41:15 -070016
17public 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
Elliott Hughes00626c22013-06-14 15:04:14 -070030 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
jeffhao5d1ac922011-09-29 17:41:15 -070093 public static void main() {
Elliott Hughes00626c22013-06-14 15:04:14 -070094 test56267();
95
jeffhao5d1ac922011-09-29 17:41:15 -070096 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
Elliott Hughes741b5b72012-01-31 19:18:51 -0800117 /* fancy */
118 printClassAttrs(FancyClass.class);
119
jeffhao5d1ac922011-09-29 17:41:15 -0700120 try {
121 Constructor cons;
122 cons = MemberClass.class.getConstructor(
123 new Class[] { MemberClass.class });
124 System.out.println("constructor signature: "
125 + getSignatureAttribute(cons));
126
127 Method meth;
128 meth = MemberClass.class.getMethod("foo", (Class[]) null);
129 System.out.println("method signature: "
130 + getSignatureAttribute(meth));
131
132 Field field;
133 field = MemberClass.class.getField("mWha");
134 System.out.println("field signature: "
135 + getSignatureAttribute(field));
136 } catch (NoSuchMethodException nsme) {
137 System.err.println("FAILED: " + nsme);
138 } catch (NoSuchFieldException nsfe) {
139 System.err.println("FAILED: " + nsfe);
140 } catch (RuntimeException re) {
141 System.err.println("FAILED: " + re);
142 re.printStackTrace();
143 }
Elliott Hughesc1503432012-03-30 17:24:47 -0700144
145 test_isAssignableFrom();
146 test_isInstance();
147 }
148
149 private static void test_isAssignableFrom() {
150 // Can always assign to things of the same type.
151 assertTrue(String.class.isAssignableFrom(String.class));
152
153 // Can assign any reference to java.lang.Object.
154 assertTrue(Object.class.isAssignableFrom(Object.class));
155 assertTrue(Object.class.isAssignableFrom(Class.class));
156 assertTrue(Object.class.isAssignableFrom(String.class));
157 assertFalse(Object.class.isAssignableFrom(int.class));
158 assertFalse(Object.class.isAssignableFrom(long.class));
159
160 // Interfaces.
161 assertTrue(CharSequence.class.isAssignableFrom(String.class));
162 assertFalse(CharSequence.class.isAssignableFrom(Object.class));
163
164 // Superclasses.
165 assertTrue(AccessibleObject.class.isAssignableFrom(Method.class));
166 assertFalse(Method.class.isAssignableFrom(AccessibleObject.class));
167
168 // Arrays.
169 assertTrue(int[].class.isAssignableFrom(int[].class));
170 assertFalse(int[].class.isAssignableFrom(char[].class));
171 assertFalse(char[].class.isAssignableFrom(int[].class));
172 assertTrue(Object.class.isAssignableFrom(int[].class));
173 assertFalse(int[].class.isAssignableFrom(Object.class));
174
175 try {
176 assertFalse(Object.class.isAssignableFrom(null));
177 fail();
178 } catch (NullPointerException expected) {
179 }
180 }
181
182 private static void test_isInstance() {
183 // Can always assign to things of the same type.
184 assertTrue(String.class.isInstance("hello"));
185
186 // Can assign any reference to java.lang.Object.
187 assertTrue(Object.class.isInstance(new Object()));
188 assertTrue(Object.class.isInstance(Class.class));
189 assertTrue(Object.class.isInstance("hello"));
190
191 // Interfaces.
192 assertTrue(CharSequence.class.isInstance("hello"));
193 assertFalse(CharSequence.class.isInstance(new Object()));
194
195 // Superclasses.
196 assertTrue(AccessibleObject.class.isInstance(Method.class.getDeclaredMethods()[0]));
197 assertFalse(Method.class.isInstance(Method.class.getDeclaredFields()[0]));
198
199 // Arrays.
200 assertTrue(int[].class.isInstance(new int[0]));
201 assertFalse(int[].class.isInstance(new char[0]));
202 assertFalse(char[].class.isInstance(new int[0]));
203 assertTrue(Object.class.isInstance(new int[0]));
204 assertFalse(int[].class.isInstance(new Object()));
205
206 assertFalse(Object.class.isInstance(null));
207 }
208
209 private static void assertTrue(boolean b) {
210 if (!b) throw new RuntimeException();
211 }
212
213 private static void assertFalse(boolean b) {
214 if (b) throw new RuntimeException();
215 }
216
217 private static void fail() {
218 throw new RuntimeException();
jeffhao5d1ac922011-09-29 17:41:15 -0700219 }
220
221 /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
222 public static String getSignatureAttribute(Object obj) {
223 Method method;
224 try {
Jeff Hao1133db72016-04-04 19:50:14 -0700225 Class c = obj.getClass();
226 if (c == Method.class || c == Constructor.class) {
227 c = AbstractMethod.class;
228 }
229 method = c.getDeclaredMethod("getSignatureAttribute");
jeffhao5d1ac922011-09-29 17:41:15 -0700230 method.setAccessible(true);
Elliott Hughes32caed42011-10-06 13:41:44 -0700231 } catch (Exception ex) {
jeffhao5d1ac922011-09-29 17:41:15 -0700232 ex.printStackTrace();
233 return "<unknown>";
234 }
235
236 try {
Jeff Hao1133db72016-04-04 19:50:14 -0700237 return (String) method.invoke(obj);
jeffhao5d1ac922011-09-29 17:41:15 -0700238 } catch (IllegalAccessException ex) {
239 throw new RuntimeException(ex);
240 } catch (InvocationTargetException ex) {
241 throw new RuntimeException(ex);
242 }
243 }
244
245 /* for reflection testing */
246 static class MemberClass<XYZ> {
247 public MemberClass<XYZ> mWha;
248
249 public MemberClass(MemberClass<XYZ> memb) {
250 mWha = memb;
251 }
252
253 public Class<XYZ> foo() throws NoSuchMethodException {
254 return null;
255 }
256 }
257
258 /* for reflection testing (getClasses vs getDeclaredClasses) */
259 static public class PublicMemberClass {
260 float mBlah;
261 }
262
263 /*
264 * Dump a variety of class attributes.
265 */
266 public static void printClassAttrs(Class clazz) {
jeffhao5d1ac922011-09-29 17:41:15 -0700267 Class clazz2;
268
269 System.out.println("***** " + clazz + ":");
270
271 System.out.println(" name: "
272 + clazz.getName());
273 System.out.println(" canonical: "
274 + clazz.getCanonicalName());
275 System.out.println(" simple: "
276 + clazz.getSimpleName());
277 System.out.println(" genericSignature: "
278 + getSignatureAttribute(clazz));
279
280 System.out.println(" super: "
281 + clazz.getSuperclass());
Elliott Hughes741b5b72012-01-31 19:18:51 -0800282 System.out.println(" genericSuperclass: "
jeffhao5d1ac922011-09-29 17:41:15 -0700283 + clazz.getGenericSuperclass());
284 System.out.println(" declaring: "
285 + clazz.getDeclaringClass());
286 System.out.println(" enclosing: "
287 + clazz.getEnclosingClass());
288 System.out.println(" enclosingCon: "
289 + clazz.getEnclosingConstructor());
290 System.out.println(" enclosingMeth: "
291 + clazz.getEnclosingMethod());
292 System.out.println(" modifiers: "
293 + clazz.getModifiers());
294 System.out.println(" package: "
295 + clazz.getPackage());
296
297 System.out.println(" declaredClasses: "
298 + stringifyTypeArray(clazz.getDeclaredClasses()));
299 System.out.println(" member classes: "
300 + stringifyTypeArray(clazz.getClasses()));
301
302 System.out.println(" isAnnotation: "
303 + clazz.isAnnotation());
304 System.out.println(" isAnonymous: "
305 + clazz.isAnonymousClass());
306 System.out.println(" isArray: "
307 + clazz.isArray());
308 System.out.println(" isEnum: "
309 + clazz.isEnum());
310 System.out.println(" isInterface: "
311 + clazz.isInterface());
312 System.out.println(" isLocalClass: "
313 + clazz.isLocalClass());
314 System.out.println(" isMemberClass: "
315 + clazz.isMemberClass());
316 System.out.println(" isPrimitive: "
317 + clazz.isPrimitive());
318 System.out.println(" isSynthetic: "
319 + clazz.isSynthetic());
320
Elliott Hughes741b5b72012-01-31 19:18:51 -0800321 System.out.println(" genericInterfaces: "
jeffhao5d1ac922011-09-29 17:41:15 -0700322 + stringifyTypeArray(clazz.getGenericInterfaces()));
Elliott Hughes741b5b72012-01-31 19:18:51 -0800323
324 TypeVariable<Class<?>>[] typeParameters = clazz.getTypeParameters();
325 System.out.println(" typeParameters: "
326 + stringifyTypeArray(typeParameters));
jeffhao5d1ac922011-09-29 17:41:15 -0700327 }
328
329 /*
330 * Convert an array of Type into a string. Start with an array count.
331 */
332 private static String stringifyTypeArray(Type[] types) {
Sebastien Hertzb1add752015-03-04 16:45:31 +0100333 List<String> typeStringList = new ArrayList<String>();
334 for (Type t : types) {
335 typeStringList.add(t.toString());
336 }
Sebastien Hertzc5e3ab22015-03-04 19:03:48 +0100337 // Sort types alphabetically so they're always printed in the same order.
338 // For instance, Class.getClasses() does not guarantee any order for the
339 // returned Class[].
Sebastien Hertzb1add752015-03-04 16:45:31 +0100340 Collections.sort(typeStringList);
341
jeffhao5d1ac922011-09-29 17:41:15 -0700342 StringBuilder stb = new StringBuilder();
343 boolean first = true;
344
345 stb.append("[" + types.length + "]");
346
Sebastien Hertzb1add752015-03-04 16:45:31 +0100347 for (String typeString : typeStringList) {
jeffhao5d1ac922011-09-29 17:41:15 -0700348 if (first) {
349 stb.append(" ");
350 first = false;
351 } else {
352 stb.append(", ");
353 }
Sebastien Hertzb1add752015-03-04 16:45:31 +0100354 stb.append(typeString);
jeffhao5d1ac922011-09-29 17:41:15 -0700355 }
356
357 return stb.toString();
358 }
359}