JAVA reflect
看了视频,老师讲的很细,写点note, 自己的理解,可能有误.仅供自己参考.
Class类的使用:
- 在面向对象的世界里,万物都是对象.
在java语言中,静态成员和普通的数据类型不是面向对象.但普通数据对象有封装,例如integer
任何类是java.lang.class类的事例对象.这个实例对象有三种表示方法.
Foo foo1 = new Foo();
/*foo1 是 Foo的实例化对象表示,而Foo又是Java.Lang.Class的实例化对象,我们称之为类类型,也就是说任何类都是lang.Class的实例化对象,而Class是不允许new Class()的, 这个实例化对象有三种表示方法*/
Class c1 = Foo.class //知道类名
Class c2 = foo1.getClass()//知道类的实例化对象
Class c3 = Class.forName("类的全称");// 知道类的全称
//c1 == c2 == c3,类类型
//我们可以通过类的类类型创建该类的对象实例
Foo foo = c1.newInstance(); //就能得到这个类对象, 需要无参的构造方法
2. Class.forName("类的全称"),不仅代表了类的类类型,类(java.lang.class)的类类型(c1),还代表了动态加载类。
2.1 编译是静态加载类,运行时刻是动态加载类。
2.2 new 对象是静态加载类,在编译时刻就需要加载所有可能使用到的类
3.
方法的反射
Method[] methods = c1.getMethods(); //public 和从父类获得的方法
Method[] methods = c2.getDeclaredMethods();//该类所声明的所有方法
然后根据方法获得方法的方法名,返回值类型,参数类型信息等
得到方法名: String methodName = methods[i].getName();
得到返回值类类型: Class returnType = methods[i].getReturnType();
返回值类型: returnType.getName();
得到参数的类类型: Class[] params = methods[i].getParameterTypes();
参数类型: params[i].getName();
成员变量的操作
Field[] fields = c.getFields(); //public
Field[] fields = c.getDeclaredFields() //该类所有的成员变量
然后获得该成员变量的类类型,类名字,成员变量的名字,
类类型:Class fieldType = fields[i].getType();
类名字:String typeName = fieldType.getName();
变量名字:String fieldName = fields[i].getName
构造函数
Class c = Class.forName(“完整的类名”);
Constructor[] cs = c.getConstructors();
Constructor[] cs = c.getDeclaredConstructors();//获取该类的构造函数
构造函数参数类类型:Class[] paramTypes = cs[i].getParameterTypes();
构造函数参数类型: paramTypes[i].getName()
方法的反射操作
先获得method,需要拿到类类型,方法名,方法参数
Class c1 = a.getClass();
Method method = c1.getMethod(“方法名”, 方法参数类型);
最后方法的反射操作
method.invoke(a, 2, 5);
如果没有返回值,返回null, 有返回值,则返回得到的值
泛型的本质
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
list1.add("zhangsan");
List2.add(10);
Class c1 = list1.getClass();
Class c2 = list2.getClass();
c1==c2 //true 由结果可以知道反射的操作都是编译之后的操作。
// 编译之后的集合泛型是去泛型的(不存在泛型的这样一说法)。
//编译之前只是为了防止错误输入。
java 中的集合泛型只是为了防止错误输入,只在编译阶段有效。
反射的操作都是编译之后的操作。
如果要进行验证,可以绕过编译操作,也就可以绕过了泛型
也就是用泛型的method.invoke()方法。