import java.util.Collection;
import java.util.Map;
import java.lang.reflect.*;

class A {
    public A[] as;
    public Collection<String> cs;
    public Map<String, Integer> msi;
    private String s;
    protected int i;
}

class Inspector {
    public static void inspect(Class<?> clazz) {
	try {
	    System.out.println("Inspecting class " + clazz.getSimpleName() + ":");
	    Field[] fields = clazz.getDeclaredFields();
	    for (Field f : fields) {
		describe(f);
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }
    
    private static void describe(Field f) throws Exception {
	describeModifiers(f);
	Type t = f.getGenericType();
	describeType(t);
	System.out.println(" " + f.getName());
    }

    private static void describeModifiers(Field f) {
	int modifiers = f.getModifiers();
	if (Modifier.isPublic(modifiers)) {
	    System.out.print(" public ");
	}
	if (Modifier.isPrivate(modifiers)) {
	    System.out.print(" private ");
	}
	if (Modifier.isProtected(modifiers)) {
	    System.out.print(" protected ");
	}
	// add more if you like
    }

    private static void describeType(Type type) {
	if (type instanceof ParameterizedType) {
	    ParameterizedType pt = (ParameterizedType) type;
	    Type[] args = pt.getActualTypeArguments();
	    System.out.print(pt.getRawType());
	    System.out.print("<");
	    boolean atBegin = true;
	    for (Type t : args) {
		if (atBegin) {
		    atBegin = false;
		} else {
		    System.out.print(", ");
		}
		describeType(t);
	    }
	    System.out.print("> ");
	
	} else if (type instanceof GenericArrayType) {
	    GenericArrayType arrType = (GenericArrayType) type;
	    describeType(arrType.getGenericComponentType());
	    System.out.println("[] ");
	} else if (type instanceof Class) {
	    Class<?> clazz = (Class) type;
	    System.out.print(clazz.getSimpleName());
	}
	// a lot of more interesing stuff can be done here
    }
}

class Main {

    public static void main(String... args) {
	Inspector.inspect(A.class);
    }
}