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 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 117 /* fancy */ 118 printClassAttrs(FancyClass.class); 119 120 try { 121 Constructor<?> cons; 122 cons = MemberClass.class.getConstructor(MemberClass.class); 123 System.out.println("constructor signature: " 124 + getSignatureAttribute(cons)); 125 126 Method meth; 127 meth = MemberClass.class.getMethod("foo"); 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 } 143 144 test_isAssignableFrom(); 145 test_isInstance(); 146 } 147 test_isAssignableFrom()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 test_isInstance()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 assertTrue(boolean b)208 private static void assertTrue(boolean b) { 209 if (!b) throw new RuntimeException(); 210 } 211 assertFalse(boolean b)212 private static void assertFalse(boolean b) { 213 if (b) throw new RuntimeException(); 214 } 215 fail()216 private static void fail() { 217 throw new RuntimeException(); 218 } 219 220 /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */ getSignatureAttribute(Object obj)221 public static String getSignatureAttribute(Object obj) { 222 Method method; 223 try { 224 Class<?> c = obj.getClass(); 225 if (c == Method.class || c == Constructor.class) { 226 c = Executable.class; 227 } 228 method = c.getDeclaredMethod("getSignatureAttribute"); 229 method.setAccessible(true); 230 } catch (Exception ex) { 231 ex.printStackTrace(); 232 return "<unknown>"; 233 } 234 235 try { 236 return (String) method.invoke(obj); 237 } 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 MemberClass(MemberClass<XYZ> memb)248 public MemberClass(MemberClass<XYZ> memb) { 249 mWha = memb; 250 } 251 foo()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 */ printClassAttrs(Class<T> clazz)265 public static <T> void printClassAttrs(Class<T> clazz) { 266 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()); 279 System.out.println(" genericSuperclass: " 280 + 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 318 System.out.println(" genericInterfaces: " 319 + stringifyTypeArray(clazz.getGenericInterfaces())); 320 321 TypeVariable<Class<T>>[] typeParameters = clazz.getTypeParameters(); 322 System.out.println(" typeParameters: " 323 + stringifyTypeArray(typeParameters)); 324 } 325 326 /* 327 * Convert an array of Type into a string. Start with an array count. 328 */ stringifyTypeArray(Type[] types)329 private static String stringifyTypeArray(Type[] types) { 330 List<String> typeStringList = new ArrayList<String>(); 331 for (Type t : types) { 332 typeStringList.add(t.toString()); 333 } 334 // 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[]. 337 Collections.sort(typeStringList); 338 339 StringBuilder stb = new StringBuilder(); 340 boolean first = true; 341 342 stb.append("[" + types.length + "]"); 343 344 for (String typeString : typeStringList) { 345 if (first) { 346 stb.append(" "); 347 first = false; 348 } else { 349 stb.append(", "); 350 } 351 stb.append(typeString); 352 } 353 354 return stb.toString(); 355 } 356 } 357