jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 1 | import otherpackage.OtherPackageClass; |
| 2 | |
| 3 | import java.lang.reflect.AccessibleObject; |
| 4 | import java.lang.reflect.Constructor; |
| 5 | import java.lang.reflect.Field; |
| 6 | import java.lang.reflect.InvocationTargetException; |
| 7 | import java.lang.reflect.Method; |
| 8 | import java.lang.reflect.Type; |
Elliott Hughes | 741b5b7 | 2012-01-31 19:18:51 -0800 | [diff] [blame] | 9 | import java.lang.reflect.TypeVariable; |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 10 | |
| 11 | public class ClassAttrs { |
| 12 | ClassAttrs() { |
| 13 | /* local, not anonymous, not member */ |
| 14 | class ConsInnerNamed { |
| 15 | public void showMe() { |
| 16 | printClassAttrs(this.getClass()); |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | ConsInnerNamed cinner = new ConsInnerNamed(); |
| 21 | cinner.showMe(); |
| 22 | } |
| 23 | |
| 24 | public static void main() { |
| 25 | printClassAttrs(ClassAttrs.class); |
| 26 | printClassAttrs(OtherClass.class); |
| 27 | printClassAttrs(OtherPackageClass.class); |
| 28 | |
| 29 | /* local, not anonymous, not member */ |
| 30 | class InnerNamed { |
| 31 | public void showMe() { |
| 32 | printClassAttrs(this.getClass()); |
| 33 | } |
| 34 | } |
| 35 | InnerNamed inner = new InnerNamed(); |
| 36 | inner.showMe(); |
| 37 | |
| 38 | ClassAttrs attrs = new ClassAttrs(); |
| 39 | |
| 40 | /* anonymous, not local, not member */ |
| 41 | printClassAttrs((new OtherClass() { int i = 5; }).getClass()); |
| 42 | |
| 43 | /* member, not anonymous, not local */ |
| 44 | printClassAttrs(MemberClass.class); |
| 45 | |
Elliott Hughes | 741b5b7 | 2012-01-31 19:18:51 -0800 | [diff] [blame] | 46 | /* fancy */ |
| 47 | printClassAttrs(FancyClass.class); |
| 48 | |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 49 | try { |
| 50 | Constructor cons; |
| 51 | cons = MemberClass.class.getConstructor( |
| 52 | new Class[] { MemberClass.class }); |
| 53 | System.out.println("constructor signature: " |
| 54 | + getSignatureAttribute(cons)); |
| 55 | |
| 56 | Method meth; |
| 57 | meth = MemberClass.class.getMethod("foo", (Class[]) null); |
| 58 | System.out.println("method signature: " |
| 59 | + getSignatureAttribute(meth)); |
| 60 | |
| 61 | Field field; |
| 62 | field = MemberClass.class.getField("mWha"); |
| 63 | System.out.println("field signature: " |
| 64 | + getSignatureAttribute(field)); |
| 65 | } catch (NoSuchMethodException nsme) { |
| 66 | System.err.println("FAILED: " + nsme); |
| 67 | } catch (NoSuchFieldException nsfe) { |
| 68 | System.err.println("FAILED: " + nsfe); |
| 69 | } catch (RuntimeException re) { |
| 70 | System.err.println("FAILED: " + re); |
| 71 | re.printStackTrace(); |
| 72 | } |
Elliott Hughes | c150343 | 2012-03-30 17:24:47 -0700 | [diff] [blame^] | 73 | |
| 74 | test_isAssignableFrom(); |
| 75 | test_isInstance(); |
| 76 | } |
| 77 | |
| 78 | private static void test_isAssignableFrom() { |
| 79 | // Can always assign to things of the same type. |
| 80 | assertTrue(String.class.isAssignableFrom(String.class)); |
| 81 | |
| 82 | // Can assign any reference to java.lang.Object. |
| 83 | assertTrue(Object.class.isAssignableFrom(Object.class)); |
| 84 | assertTrue(Object.class.isAssignableFrom(Class.class)); |
| 85 | assertTrue(Object.class.isAssignableFrom(String.class)); |
| 86 | assertFalse(Object.class.isAssignableFrom(int.class)); |
| 87 | assertFalse(Object.class.isAssignableFrom(long.class)); |
| 88 | |
| 89 | // Interfaces. |
| 90 | assertTrue(CharSequence.class.isAssignableFrom(String.class)); |
| 91 | assertFalse(CharSequence.class.isAssignableFrom(Object.class)); |
| 92 | |
| 93 | // Superclasses. |
| 94 | assertTrue(AccessibleObject.class.isAssignableFrom(Method.class)); |
| 95 | assertFalse(Method.class.isAssignableFrom(AccessibleObject.class)); |
| 96 | |
| 97 | // Arrays. |
| 98 | assertTrue(int[].class.isAssignableFrom(int[].class)); |
| 99 | assertFalse(int[].class.isAssignableFrom(char[].class)); |
| 100 | assertFalse(char[].class.isAssignableFrom(int[].class)); |
| 101 | assertTrue(Object.class.isAssignableFrom(int[].class)); |
| 102 | assertFalse(int[].class.isAssignableFrom(Object.class)); |
| 103 | |
| 104 | try { |
| 105 | assertFalse(Object.class.isAssignableFrom(null)); |
| 106 | fail(); |
| 107 | } catch (NullPointerException expected) { |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | private static void test_isInstance() { |
| 112 | // Can always assign to things of the same type. |
| 113 | assertTrue(String.class.isInstance("hello")); |
| 114 | |
| 115 | // Can assign any reference to java.lang.Object. |
| 116 | assertTrue(Object.class.isInstance(new Object())); |
| 117 | assertTrue(Object.class.isInstance(Class.class)); |
| 118 | assertTrue(Object.class.isInstance("hello")); |
| 119 | |
| 120 | // Interfaces. |
| 121 | assertTrue(CharSequence.class.isInstance("hello")); |
| 122 | assertFalse(CharSequence.class.isInstance(new Object())); |
| 123 | |
| 124 | // Superclasses. |
| 125 | assertTrue(AccessibleObject.class.isInstance(Method.class.getDeclaredMethods()[0])); |
| 126 | assertFalse(Method.class.isInstance(Method.class.getDeclaredFields()[0])); |
| 127 | |
| 128 | // Arrays. |
| 129 | assertTrue(int[].class.isInstance(new int[0])); |
| 130 | assertFalse(int[].class.isInstance(new char[0])); |
| 131 | assertFalse(char[].class.isInstance(new int[0])); |
| 132 | assertTrue(Object.class.isInstance(new int[0])); |
| 133 | assertFalse(int[].class.isInstance(new Object())); |
| 134 | |
| 135 | assertFalse(Object.class.isInstance(null)); |
| 136 | } |
| 137 | |
| 138 | private static void assertTrue(boolean b) { |
| 139 | if (!b) throw new RuntimeException(); |
| 140 | } |
| 141 | |
| 142 | private static void assertFalse(boolean b) { |
| 143 | if (b) throw new RuntimeException(); |
| 144 | } |
| 145 | |
| 146 | private static void fail() { |
| 147 | throw new RuntimeException(); |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 148 | } |
| 149 | |
| 150 | /* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */ |
| 151 | public static String getSignatureAttribute(Object obj) { |
| 152 | Method method; |
| 153 | try { |
Elliott Hughes | 32caed4 | 2011-10-06 13:41:44 -0700 | [diff] [blame] | 154 | Class c = Class.forName("libcore.reflect.AnnotationAccess"); |
| 155 | method = c.getDeclaredMethod("getSignature", java.lang.reflect.AnnotatedElement.class); |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 156 | method.setAccessible(true); |
Elliott Hughes | 32caed4 | 2011-10-06 13:41:44 -0700 | [diff] [blame] | 157 | } catch (Exception ex) { |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 158 | ex.printStackTrace(); |
| 159 | return "<unknown>"; |
| 160 | } |
| 161 | |
| 162 | try { |
Elliott Hughes | 32caed4 | 2011-10-06 13:41:44 -0700 | [diff] [blame] | 163 | return (String) method.invoke(null, obj); |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 164 | } catch (IllegalAccessException ex) { |
| 165 | throw new RuntimeException(ex); |
| 166 | } catch (InvocationTargetException ex) { |
| 167 | throw new RuntimeException(ex); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | /* for reflection testing */ |
| 172 | static class MemberClass<XYZ> { |
| 173 | public MemberClass<XYZ> mWha; |
| 174 | |
| 175 | public MemberClass(MemberClass<XYZ> memb) { |
| 176 | mWha = memb; |
| 177 | } |
| 178 | |
| 179 | public Class<XYZ> foo() throws NoSuchMethodException { |
| 180 | return null; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | /* for reflection testing (getClasses vs getDeclaredClasses) */ |
| 185 | static public class PublicMemberClass { |
| 186 | float mBlah; |
| 187 | } |
| 188 | |
| 189 | /* |
| 190 | * Dump a variety of class attributes. |
| 191 | */ |
| 192 | public static void printClassAttrs(Class clazz) { |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 193 | Class clazz2; |
| 194 | |
| 195 | System.out.println("***** " + clazz + ":"); |
| 196 | |
| 197 | System.out.println(" name: " |
| 198 | + clazz.getName()); |
| 199 | System.out.println(" canonical: " |
| 200 | + clazz.getCanonicalName()); |
| 201 | System.out.println(" simple: " |
| 202 | + clazz.getSimpleName()); |
| 203 | System.out.println(" genericSignature: " |
| 204 | + getSignatureAttribute(clazz)); |
| 205 | |
| 206 | System.out.println(" super: " |
| 207 | + clazz.getSuperclass()); |
Elliott Hughes | 741b5b7 | 2012-01-31 19:18:51 -0800 | [diff] [blame] | 208 | System.out.println(" genericSuperclass: " |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 209 | + clazz.getGenericSuperclass()); |
| 210 | System.out.println(" declaring: " |
| 211 | + clazz.getDeclaringClass()); |
| 212 | System.out.println(" enclosing: " |
| 213 | + clazz.getEnclosingClass()); |
| 214 | System.out.println(" enclosingCon: " |
| 215 | + clazz.getEnclosingConstructor()); |
| 216 | System.out.println(" enclosingMeth: " |
| 217 | + clazz.getEnclosingMethod()); |
| 218 | System.out.println(" modifiers: " |
| 219 | + clazz.getModifiers()); |
| 220 | System.out.println(" package: " |
| 221 | + clazz.getPackage()); |
| 222 | |
| 223 | System.out.println(" declaredClasses: " |
| 224 | + stringifyTypeArray(clazz.getDeclaredClasses())); |
| 225 | System.out.println(" member classes: " |
| 226 | + stringifyTypeArray(clazz.getClasses())); |
| 227 | |
| 228 | System.out.println(" isAnnotation: " |
| 229 | + clazz.isAnnotation()); |
| 230 | System.out.println(" isAnonymous: " |
| 231 | + clazz.isAnonymousClass()); |
| 232 | System.out.println(" isArray: " |
| 233 | + clazz.isArray()); |
| 234 | System.out.println(" isEnum: " |
| 235 | + clazz.isEnum()); |
| 236 | System.out.println(" isInterface: " |
| 237 | + clazz.isInterface()); |
| 238 | System.out.println(" isLocalClass: " |
| 239 | + clazz.isLocalClass()); |
| 240 | System.out.println(" isMemberClass: " |
| 241 | + clazz.isMemberClass()); |
| 242 | System.out.println(" isPrimitive: " |
| 243 | + clazz.isPrimitive()); |
| 244 | System.out.println(" isSynthetic: " |
| 245 | + clazz.isSynthetic()); |
| 246 | |
Elliott Hughes | 741b5b7 | 2012-01-31 19:18:51 -0800 | [diff] [blame] | 247 | System.out.println(" genericInterfaces: " |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 248 | + stringifyTypeArray(clazz.getGenericInterfaces())); |
Elliott Hughes | 741b5b7 | 2012-01-31 19:18:51 -0800 | [diff] [blame] | 249 | |
| 250 | TypeVariable<Class<?>>[] typeParameters = clazz.getTypeParameters(); |
| 251 | System.out.println(" typeParameters: " |
| 252 | + stringifyTypeArray(typeParameters)); |
jeffhao | 5d1ac92 | 2011-09-29 17:41:15 -0700 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | /* |
| 256 | * Convert an array of Type into a string. Start with an array count. |
| 257 | */ |
| 258 | private static String stringifyTypeArray(Type[] types) { |
| 259 | StringBuilder stb = new StringBuilder(); |
| 260 | boolean first = true; |
| 261 | |
| 262 | stb.append("[" + types.length + "]"); |
| 263 | |
| 264 | for (Type t: types) { |
| 265 | if (first) { |
| 266 | stb.append(" "); |
| 267 | first = false; |
| 268 | } else { |
| 269 | stb.append(", "); |
| 270 | } |
| 271 | stb.append(t.toString()); |
| 272 | } |
| 273 | |
| 274 | return stb.toString(); |
| 275 | } |
| 276 | } |