Class c1 = Student.class; // 实际告诉我们任何一个类都有一个隐含的静态成员变量class(知道类名时用)
Student stu = new Student();
Class c2 = stu.getClass(); // 已知该类的对象通过getClass方法(知道对象时用)
try {
Class c3 = Class.forName("com.cnblogs.reflect.Student");// 会有一个ClassNotFoundException异常
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ps: 官网解释说, c1, c2表示 Student类的类类型(class type), 类也是对象, 是Class类的实例对象, 这个对象我们称之为该类的类类型
这里有一点值得注意的是: 当我们执行System.out.println(c1 == c2)
时, 结果是true
, 这是为什么? 原因是不管c1, c2都代表了Student类的类类型, 一个类可能是Class类的一个实例对象.
我们完全可以通过类的类类型创建该类的对象实例, 即通过c1或者c2创建Student的实例;
Student stu = (Student) c1.newInstance(); // 前提是Student里必须要有无参构造方法, 否则会报异常
Class c = Class.forName(“类全名”)
, 不仅表示了类的类型, 还表示了动态加载类, 编译不会报错, 在运行时才会加载, 使用接口标准能更方便胴体加载类的实现. 功能性的类尽量使用动态加载, 而不用静态加载.void
关键字都存在类类型Class c1 = int.class; // int的类类型
Class c2 = String.class; // String的类类型, 可以理解为编译生成生成的那个String.class字节码文件
Class c3 = double.class;
Class c4 = Double.class;
Class c5 = void.class;
public static void printClassMessage(Object obj) {
Class c = obj.getClass();
// 获取类的类名称;
System.out.println("类的名称是: " + c.getName());
System.out.println("---------------------------------");
Method[] methods = c.getMethods();
for (Method method : methods) {
// 得到方法返回值类型的类类型
Class returnType = method.getReturnType();
System.out.println("returnType = " + returnType.getName());
// 得到方法的名称
System.out.println("method = " + method.getName());
// 获取参数类型 -> 得到的是参数列表的类类型
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class parameterClass : parameterTypes) {
System.out.println("parameterClass = " + parameterClass.getName());
}
System.out.println("---------------------------------");
}
}
public static void printFieldMessgae(Object obj) {
Class<?> c = obj.getClass();
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 得到成员变量的类型的类类型
Class<?> fieldType = field.getType();
String typeName = fieldType.getName();
System.out.println("typeName = " + typeName);
// 得到成员变量的名称
String fieldName = field.getName();
System.out.println("fieldName = " + fieldName);
}
/**
* 获取构造函数
*/
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("constructor = " + constructor.getName());
/**
* 获取构造函数的参数的类类型
*/
Class<?>[] parameterTypes = constructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("parameterType = " + parameterType.getName());
}
}
}
Method m = c.getDeclaredMethod("方法名", 可变参数列表(参数类型.class))
m.invoke(对象, 参数列表)
ArrayList list1 = new ArrayList();
ArrayList<String> list2 = new ArrayList();
Class c1 = list1.getClass();
Class c2 = list2.getClass();
System.out.println(c1 == c2); // -> true
Ps: 因为反射的操作都是编译之后的操作, 也就是运行时的操作, c1 == c2
返回true
, 说明编译之后集合的泛型是去泛型化的.
那么我们可以理解为, Java集合中的泛型, 是用于泛指错误类型元素输入的, 比如在list2中我们add一个int,
原文:https://www.cnblogs.com/liuyishi/p/10353676.html