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