blob: 39e69a3066a9aea73eda67e86eedad8878260b47 [file] [log] [blame]
import otherpackage.OtherPackageClass;
import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ClassAttrs {
ClassAttrs() {
/* local, not anonymous, not member */
class ConsInnerNamed {
public void showMe() {
printClassAttrs(this.getClass());
}
}
ConsInnerNamed cinner = new ConsInnerNamed();
cinner.showMe();
}
public class PublicInnerClass {
}
protected class ProtectedInnerClass {
}
private class PrivateInnerClass {
}
class PackagePrivateInnerClass {
}
public interface PublicInnerInterface {
}
protected interface ProtectedInnerInterface {
}
private interface PrivateInnerInterface {
}
interface PackagePrivateInnerInterface {
}
private static void showModifiers(Class<?> c) {
System.out.println(Modifier.toString(c.getModifiers()) + " " + c.getName());
}
// https://code.google.com/p/android/issues/detail?id=56267
private static void test56267() {
// Primitive classes.
showModifiers(int.class);
showModifiers(int[].class);
// Regular classes.
showModifiers(Object.class);
showModifiers(Object[].class);
// Inner classes.
showModifiers(PublicInnerClass.class);
showModifiers(PublicInnerClass[].class);
showModifiers(ProtectedInnerClass.class);
showModifiers(ProtectedInnerClass[].class);
showModifiers(PrivateInnerClass.class);
showModifiers(PrivateInnerClass[].class);
showModifiers(PackagePrivateInnerClass.class);
showModifiers(PackagePrivateInnerClass[].class);
// Regular interfaces.
showModifiers(Serializable.class);
showModifiers(Serializable[].class);
// Inner interfaces.
showModifiers(PublicInnerInterface.class);
showModifiers(PublicInnerInterface[].class);
showModifiers(ProtectedInnerInterface.class);
showModifiers(ProtectedInnerInterface[].class);
showModifiers(PrivateInnerInterface.class);
showModifiers(PrivateInnerInterface[].class);
showModifiers(PackagePrivateInnerInterface.class);
showModifiers(PackagePrivateInnerInterface[].class);
}
public static void main() {
test56267();
printClassAttrs(ClassAttrs.class);
printClassAttrs(OtherClass.class);
printClassAttrs(OtherPackageClass.class);
/* local, not anonymous, not member */
class InnerNamed {
public void showMe() {
printClassAttrs(this.getClass());
}
}
InnerNamed inner = new InnerNamed();
inner.showMe();
ClassAttrs attrs = new ClassAttrs();
/* anonymous, not local, not member */
printClassAttrs((new OtherClass() { int i = 5; }).getClass());
/* member, not anonymous, not local */
printClassAttrs(MemberClass.class);
/* fancy */
printClassAttrs(FancyClass.class);
try {
Constructor<?> cons;
cons = MemberClass.class.getConstructor(MemberClass.class);
System.out.println("constructor signature: "
+ getSignatureAttribute(cons));
Method meth;
meth = MemberClass.class.getMethod("foo");
System.out.println("method signature: "
+ getSignatureAttribute(meth));
Field field;
field = MemberClass.class.getField("mWha");
System.out.println("field signature: "
+ getSignatureAttribute(field));
} catch (NoSuchMethodException nsme) {
System.err.println("FAILED: " + nsme);
} catch (NoSuchFieldException nsfe) {
System.err.println("FAILED: " + nsfe);
} catch (RuntimeException re) {
System.err.println("FAILED: " + re);
re.printStackTrace();
}
test_isAssignableFrom();
test_isInstance();
}
private static void test_isAssignableFrom() {
// Can always assign to things of the same type.
assertTrue(String.class.isAssignableFrom(String.class));
// Can assign any reference to java.lang.Object.
assertTrue(Object.class.isAssignableFrom(Object.class));
assertTrue(Object.class.isAssignableFrom(Class.class));
assertTrue(Object.class.isAssignableFrom(String.class));
assertFalse(Object.class.isAssignableFrom(int.class));
assertFalse(Object.class.isAssignableFrom(long.class));
// Interfaces.
assertTrue(CharSequence.class.isAssignableFrom(String.class));
assertFalse(CharSequence.class.isAssignableFrom(Object.class));
// Superclasses.
assertTrue(AccessibleObject.class.isAssignableFrom(Method.class));
assertFalse(Method.class.isAssignableFrom(AccessibleObject.class));
// Arrays.
assertTrue(int[].class.isAssignableFrom(int[].class));
assertFalse(int[].class.isAssignableFrom(char[].class));
assertFalse(char[].class.isAssignableFrom(int[].class));
assertTrue(Object.class.isAssignableFrom(int[].class));
assertFalse(int[].class.isAssignableFrom(Object.class));
try {
assertFalse(Object.class.isAssignableFrom(null));
fail();
} catch (NullPointerException expected) {
}
}
private static void test_isInstance() {
// Can always assign to things of the same type.
assertTrue(String.class.isInstance("hello"));
// Can assign any reference to java.lang.Object.
assertTrue(Object.class.isInstance(new Object()));
assertTrue(Object.class.isInstance(Class.class));
assertTrue(Object.class.isInstance("hello"));
// Interfaces.
assertTrue(CharSequence.class.isInstance("hello"));
assertFalse(CharSequence.class.isInstance(new Object()));
// Superclasses.
assertTrue(AccessibleObject.class.isInstance(Method.class.getDeclaredMethods()[0]));
assertFalse(Method.class.isInstance(Method.class.getDeclaredFields()[0]));
// Arrays.
assertTrue(int[].class.isInstance(new int[0]));
assertFalse(int[].class.isInstance(new char[0]));
assertFalse(char[].class.isInstance(new int[0]));
assertTrue(Object.class.isInstance(new int[0]));
assertFalse(int[].class.isInstance(new Object()));
assertFalse(Object.class.isInstance(null));
}
private static void assertTrue(boolean b) {
if (!b) throw new RuntimeException();
}
private static void assertFalse(boolean b) {
if (b) throw new RuntimeException();
}
private static void fail() {
throw new RuntimeException();
}
/* to call the (out-of-scope) <code>getSignatureAttribute</code> methods */
public static String getSignatureAttribute(Object obj) {
Method method;
try {
Class<?> c = obj.getClass();
if (c == Method.class || c == Constructor.class) {
c = Executable.class;
}
method = c.getDeclaredMethod("getSignatureAttribute");
method.setAccessible(true);
} catch (Exception ex) {
ex.printStackTrace();
return "<unknown>";
}
try {
return (String) method.invoke(obj);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
/* for reflection testing */
static class MemberClass<XYZ> {
public MemberClass<XYZ> mWha;
public MemberClass(MemberClass<XYZ> memb) {
mWha = memb;
}
public Class<XYZ> foo() throws NoSuchMethodException {
return null;
}
}
/* for reflection testing (getClasses vs getDeclaredClasses) */
static public class PublicMemberClass {
float mBlah;
}
/*
* Dump a variety of class attributes.
*/
public static <T> void printClassAttrs(Class<T> clazz) {
System.out.println("***** " + clazz + ":");
System.out.println(" name: "
+ clazz.getName());
System.out.println(" canonical: "
+ clazz.getCanonicalName());
System.out.println(" simple: "
+ clazz.getSimpleName());
System.out.println(" genericSignature: "
+ getSignatureAttribute(clazz));
System.out.println(" super: "
+ clazz.getSuperclass());
System.out.println(" genericSuperclass: "
+ clazz.getGenericSuperclass());
System.out.println(" declaring: "
+ clazz.getDeclaringClass());
System.out.println(" enclosing: "
+ clazz.getEnclosingClass());
System.out.println(" enclosingCon: "
+ clazz.getEnclosingConstructor());
System.out.println(" enclosingMeth: "
+ clazz.getEnclosingMethod());
System.out.println(" modifiers: "
+ clazz.getModifiers());
System.out.println(" package: "
+ clazz.getPackage());
System.out.println(" declaredClasses: "
+ stringifyTypeArray(clazz.getDeclaredClasses()));
System.out.println(" member classes: "
+ stringifyTypeArray(clazz.getClasses()));
System.out.println(" isAnnotation: "
+ clazz.isAnnotation());
System.out.println(" isAnonymous: "
+ clazz.isAnonymousClass());
System.out.println(" isArray: "
+ clazz.isArray());
System.out.println(" isEnum: "
+ clazz.isEnum());
System.out.println(" isInterface: "
+ clazz.isInterface());
System.out.println(" isLocalClass: "
+ clazz.isLocalClass());
System.out.println(" isMemberClass: "
+ clazz.isMemberClass());
System.out.println(" isPrimitive: "
+ clazz.isPrimitive());
System.out.println(" isSynthetic: "
+ clazz.isSynthetic());
System.out.println(" genericInterfaces: "
+ stringifyTypeArray(clazz.getGenericInterfaces()));
TypeVariable<Class<T>>[] typeParameters = clazz.getTypeParameters();
System.out.println(" typeParameters: "
+ stringifyTypeArray(typeParameters));
}
/*
* Convert an array of Type into a string. Start with an array count.
*/
private static String stringifyTypeArray(Type[] types) {
List<String> typeStringList = new ArrayList<String>();
for (Type t : types) {
typeStringList.add(t.toString());
}
// Sort types alphabetically so they're always printed in the same order.
// For instance, Class.getClasses() does not guarantee any order for the
// returned Class[].
Collections.sort(typeStringList);
StringBuilder stb = new StringBuilder();
boolean first = true;
stb.append("[" + types.length + "]");
for (String typeString : typeStringList) {
if (first) {
stb.append(" ");
first = false;
} else {
stb.append(", ");
}
stb.append(typeString);
}
return stb.toString();
}
}