blob: f55a34c5f2558c6c228bf7efe45cd50752256aa9 [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;
Neil Fuller0e844392016-09-08 13:43:31 +01006import java.lang.reflect.Executable;
jeffhao5d1ac922011-09-29 17:41:15 -07007import 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();
Tobias Thiererbb68b222017-12-11 22:29:17 +0000110 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 }
jeffhao5d1ac922011-09-29 17:41:15 -0700118
119 /* member, not anonymous, not local */
120 printClassAttrs(MemberClass.class);
121
Elliott Hughes741b5b72012-01-31 19:18:51 -0800122 /* fancy */
123 printClassAttrs(FancyClass.class);
124
jeffhao5d1ac922011-09-29 17:41:15 -0700125 try {
Andreas Gampe166aaee2016-07-18 08:27:23 -0700126 Constructor<?> cons;
127 cons = MemberClass.class.getConstructor(MemberClass.class);
jeffhao5d1ac922011-09-29 17:41:15 -0700128 System.out.println("constructor signature: "
129 + getSignatureAttribute(cons));
130
131 Method meth;
Andreas Gampe166aaee2016-07-18 08:27:23 -0700132 meth = MemberClass.class.getMethod("foo");
jeffhao5d1ac922011-09-29 17:41:15 -0700133 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) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000141 System.out.println("FAILED: " + nsme);
jeffhao5d1ac922011-09-29 17:41:15 -0700142 } catch (NoSuchFieldException nsfe) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000143 System.out.println("FAILED: " + nsfe);
jeffhao5d1ac922011-09-29 17:41:15 -0700144 } catch (RuntimeException re) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000145 System.out.println("FAILED: " + re);
146 re.printStackTrace(System.out);
jeffhao5d1ac922011-09-29 17:41:15 -0700147 }
Elliott Hughesc1503432012-03-30 17:24:47 -0700148
149 test_isAssignableFrom();
150 test_isInstance();
151 }
152
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
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
213 private static void assertTrue(boolean b) {
214 if (!b) throw new RuntimeException();
215 }
216
217 private static void assertFalse(boolean b) {
218 if (b) throw new RuntimeException();
219 }
220
221 private static void fail() {
222 throw new RuntimeException();
jeffhao5d1ac922011-09-29 17:41:15 -0700223 }
224
225 /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
226 public static String getSignatureAttribute(Object obj) {
227 Method method;
228 try {
Andreas Gampe166aaee2016-07-18 08:27:23 -0700229 Class<?> c = obj.getClass();
Jeff Hao1133db72016-04-04 19:50:14 -0700230 if (c == Method.class || c == Constructor.class) {
Neil Fuller0e844392016-09-08 13:43:31 +0100231 c = Executable.class;
Jeff Hao1133db72016-04-04 19:50:14 -0700232 }
233 method = c.getDeclaredMethod("getSignatureAttribute");
jeffhao5d1ac922011-09-29 17:41:15 -0700234 method.setAccessible(true);
Elliott Hughes32caed42011-10-06 13:41:44 -0700235 } catch (Exception ex) {
Kevin Brodskyf6c66c32015-12-17 14:13:00 +0000236 ex.printStackTrace(System.out);
jeffhao5d1ac922011-09-29 17:41:15 -0700237 return "<unknown>";
238 }
239
240 try {
Jeff Hao1133db72016-04-04 19:50:14 -0700241 return (String) method.invoke(obj);
jeffhao5d1ac922011-09-29 17:41:15 -0700242 } 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
253 public MemberClass(MemberClass<XYZ> memb) {
254 mWha = memb;
255 }
256
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 */
Andreas Gampe166aaee2016-07-18 08:27:23 -0700270 public static <T> void printClassAttrs(Class<T> clazz) {
jeffhao5d1ac922011-09-29 17:41:15 -0700271 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());
Elliott Hughes741b5b72012-01-31 19:18:51 -0800284 System.out.println(" genericSuperclass: "
jeffhao5d1ac922011-09-29 17:41:15 -0700285 + 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
Elliott Hughes741b5b72012-01-31 19:18:51 -0800323 System.out.println(" genericInterfaces: "
jeffhao5d1ac922011-09-29 17:41:15 -0700324 + stringifyTypeArray(clazz.getGenericInterfaces()));
Elliott Hughes741b5b72012-01-31 19:18:51 -0800325
Andreas Gampe166aaee2016-07-18 08:27:23 -0700326 TypeVariable<Class<T>>[] typeParameters = clazz.getTypeParameters();
Elliott Hughes741b5b72012-01-31 19:18:51 -0800327 System.out.println(" typeParameters: "
328 + stringifyTypeArray(typeParameters));
jeffhao5d1ac922011-09-29 17:41:15 -0700329 }
330
331 /*
332 * Convert an array of Type into a string. Start with an array count.
333 */
334 private static String stringifyTypeArray(Type[] types) {
Sebastien Hertzb1add752015-03-04 16:45:31 +0100335 List<String> typeStringList = new ArrayList<String>();
336 for (Type t : types) {
337 typeStringList.add(t.toString());
338 }
Sebastien Hertzc5e3ab22015-03-04 19:03:48 +0100339 // 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[].
Sebastien Hertzb1add752015-03-04 16:45:31 +0100342 Collections.sort(typeStringList);
343
jeffhao5d1ac922011-09-29 17:41:15 -0700344 StringBuilder stb = new StringBuilder();
345 boolean first = true;
346
347 stb.append("[" + types.length + "]");
348
Sebastien Hertzb1add752015-03-04 16:45:31 +0100349 for (String typeString : typeStringList) {
jeffhao5d1ac922011-09-29 17:41:15 -0700350 if (first) {
351 stb.append(" ");
352 first = false;
353 } else {
354 stb.append(", ");
355 }
Sebastien Hertzb1add752015-03-04 16:45:31 +0100356 stb.append(typeString);
jeffhao5d1ac922011-09-29 17:41:15 -0700357 }
358
359 return stb.toString();
360 }
361}