blob: 346e13d11048b0f3d3f6317f8e59473bdf56e40e [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 {
Andreas Gampe166aaee2016-07-18 08:27:23 -0700121 Constructor<?> cons;
122 cons = MemberClass.class.getConstructor(MemberClass.class);
jeffhao5d1ac922011-09-29 17:41:15 -0700123 System.out.println("constructor signature: "
124 + getSignatureAttribute(cons));
125
126 Method meth;
Andreas Gampe166aaee2016-07-18 08:27:23 -0700127 meth = MemberClass.class.getMethod("foo");
jeffhao5d1ac922011-09-29 17:41:15 -0700128 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 {
Andreas Gampe166aaee2016-07-18 08:27:23 -0700224 Class<?> c = obj.getClass();
Jeff Hao1133db72016-04-04 19:50:14 -0700225 if (c == Method.class || c == Constructor.class) {
226 c = AbstractMethod.class;
227 }
228 method = c.getDeclaredMethod("getSignatureAttribute");
jeffhao5d1ac922011-09-29 17:41:15 -0700229 method.setAccessible(true);
Elliott Hughes32caed42011-10-06 13:41:44 -0700230 } catch (Exception ex) {
jeffhao5d1ac922011-09-29 17:41:15 -0700231 ex.printStackTrace();
232 return "<unknown>";
233 }
234
235 try {
Jeff Hao1133db72016-04-04 19:50:14 -0700236 return (String) method.invoke(obj);
jeffhao5d1ac922011-09-29 17:41:15 -0700237 } catch (IllegalAccessException ex) {
238 throw new RuntimeException(ex);
239 } catch (InvocationTargetException ex) {
240 throw new RuntimeException(ex);
241 }
242 }
243
244 /* for reflection testing */
245 static class MemberClass<XYZ> {
246 public MemberClass<XYZ> mWha;
247
248 public MemberClass(MemberClass<XYZ> memb) {
249 mWha = memb;
250 }
251
252 public Class<XYZ> foo() throws NoSuchMethodException {
253 return null;
254 }
255 }
256
257 /* for reflection testing (getClasses vs getDeclaredClasses) */
258 static public class PublicMemberClass {
259 float mBlah;
260 }
261
262 /*
263 * Dump a variety of class attributes.
264 */
Andreas Gampe166aaee2016-07-18 08:27:23 -0700265 public static <T> void printClassAttrs(Class<T> clazz) {
jeffhao5d1ac922011-09-29 17:41:15 -0700266 System.out.println("***** " + clazz + ":");
267
268 System.out.println(" name: "
269 + clazz.getName());
270 System.out.println(" canonical: "
271 + clazz.getCanonicalName());
272 System.out.println(" simple: "
273 + clazz.getSimpleName());
274 System.out.println(" genericSignature: "
275 + getSignatureAttribute(clazz));
276
277 System.out.println(" super: "
278 + clazz.getSuperclass());
Elliott Hughes741b5b72012-01-31 19:18:51 -0800279 System.out.println(" genericSuperclass: "
jeffhao5d1ac922011-09-29 17:41:15 -0700280 + clazz.getGenericSuperclass());
281 System.out.println(" declaring: "
282 + clazz.getDeclaringClass());
283 System.out.println(" enclosing: "
284 + clazz.getEnclosingClass());
285 System.out.println(" enclosingCon: "
286 + clazz.getEnclosingConstructor());
287 System.out.println(" enclosingMeth: "
288 + clazz.getEnclosingMethod());
289 System.out.println(" modifiers: "
290 + clazz.getModifiers());
291 System.out.println(" package: "
292 + clazz.getPackage());
293
294 System.out.println(" declaredClasses: "
295 + stringifyTypeArray(clazz.getDeclaredClasses()));
296 System.out.println(" member classes: "
297 + stringifyTypeArray(clazz.getClasses()));
298
299 System.out.println(" isAnnotation: "
300 + clazz.isAnnotation());
301 System.out.println(" isAnonymous: "
302 + clazz.isAnonymousClass());
303 System.out.println(" isArray: "
304 + clazz.isArray());
305 System.out.println(" isEnum: "
306 + clazz.isEnum());
307 System.out.println(" isInterface: "
308 + clazz.isInterface());
309 System.out.println(" isLocalClass: "
310 + clazz.isLocalClass());
311 System.out.println(" isMemberClass: "
312 + clazz.isMemberClass());
313 System.out.println(" isPrimitive: "
314 + clazz.isPrimitive());
315 System.out.println(" isSynthetic: "
316 + clazz.isSynthetic());
317
Elliott Hughes741b5b72012-01-31 19:18:51 -0800318 System.out.println(" genericInterfaces: "
jeffhao5d1ac922011-09-29 17:41:15 -0700319 + stringifyTypeArray(clazz.getGenericInterfaces()));
Elliott Hughes741b5b72012-01-31 19:18:51 -0800320
Andreas Gampe166aaee2016-07-18 08:27:23 -0700321 TypeVariable<Class<T>>[] typeParameters = clazz.getTypeParameters();
Elliott Hughes741b5b72012-01-31 19:18:51 -0800322 System.out.println(" typeParameters: "
323 + stringifyTypeArray(typeParameters));
jeffhao5d1ac922011-09-29 17:41:15 -0700324 }
325
326 /*
327 * Convert an array of Type into a string. Start with an array count.
328 */
329 private static String stringifyTypeArray(Type[] types) {
Sebastien Hertzb1add752015-03-04 16:45:31 +0100330 List<String> typeStringList = new ArrayList<String>();
331 for (Type t : types) {
332 typeStringList.add(t.toString());
333 }
Sebastien Hertzc5e3ab22015-03-04 19:03:48 +0100334 // Sort types alphabetically so they're always printed in the same order.
335 // For instance, Class.getClasses() does not guarantee any order for the
336 // returned Class[].
Sebastien Hertzb1add752015-03-04 16:45:31 +0100337 Collections.sort(typeStringList);
338
jeffhao5d1ac922011-09-29 17:41:15 -0700339 StringBuilder stb = new StringBuilder();
340 boolean first = true;
341
342 stb.append("[" + types.length + "]");
343
Sebastien Hertzb1add752015-03-04 16:45:31 +0100344 for (String typeString : typeStringList) {
jeffhao5d1ac922011-09-29 17:41:15 -0700345 if (first) {
346 stb.append(" ");
347 first = false;
348 } else {
349 stb.append(", ");
350 }
Sebastien Hertzb1add752015-03-04 16:45:31 +0100351 stb.append(typeString);
jeffhao5d1ac922011-09-29 17:41:15 -0700352 }
353
354 return stb.toString();
355 }
356}