一、Class类
(1)类是对象,类是java.lang.Class的实例对象
(2)数据类型不是对象,静态的东西也不是对象
(3)Class类的对象表示:如 Class A{}
//A类的实例对象如何表示
A a = new A(); //a就表示A类的实例对象
//任何一个类都是Class类的实例对象,有三种表示形式
//第一种→实际在告诉我们任何一个类都有一个隐含的静态成员变量class
Class a_one = A.class;
//第二种→已经知道该类的对象,通过getClass方法
Class a_two = a.getClass();
//a_one 和 a_two 都表示了A类的类类型
//第三种
Class a_tri = null;
a_tri = Class.forName("com.demo.A");//会抛出ClassNotFound异常
//可以通过类的类类型创建该类的对象实例
A a = (A)a_one.newInstance();//需要有无参构造方法(会抛出ClassNotFound异常)
二、动态加载类
Class.forName(“包名+类的名称”);
(1)不仅表示了类的类类型,还代表了动态加载类
(2)编译时刻加载类是静态加载类,运行时刻加载类是动态加载类
//new 创建的对象是静态加载类,在编译时刻就需要加载所有可能用到的类
//Class.forName()是动态加载类,在运行时刻加载,并可通过类类型的newInstance方法创建该类的对象
三、获取方法信息
(1)数据类型也有类类型
Class i_c = int.class;//int的类类型
Class s_c = String.class;//String的类类型
System.out.pringln(i_c.getName());//输出结果→int
System.out.pringln(s_c.getName());//输出结果→java.lang.String
System.out.pringln(s_c.getSimpleName())//输出结果→String(不包含包名的类名称)
(2)获取类的信息
public static void getClassMsg(Object obj){
//先获取类的类类型
Class c = obj.getClass();//传递的是哪个子类,c就是哪个子类的类类型
//获取类的名称
c.getName();
/**
*Method类,方法对象
*一个成员方法就是一个Method对象
*getMethods()获取的是所有public的函数,包括父类
*getDeclaredMethods()获取的是所有该类自己声明的方法,不需要访问权限
*/
Method[] ms = c.getMethods();
for(Method m : ms){
//得到方法的返回值类型
Class returnType = m.getReturnType();
//得到方法名
m.getName();
//参数类型
Class[] params = m.getParamterTypes();
}
}
四、获取成员变量的构造函数
/*
*成员变量也是对象
*java.lang.reflect.Field
*Field类封装了关于成员变量的操作
*getFields()获取所有的public的成员变量信息
*getDeclaredFields()获取该类自己声明的成员变量信息
*/
Field[] fs = c.getDeclaredFields();
for(Field f : fs){
//得到成员变量的类型的类类型
Class fieldType = f.getType();
//类型名称
fieldType.getName();
//变量名称
f.getName();
}
//构造函数也是对象,java.lang.Constructor中封装了构造函数的信息
Constructor[] cs = c.getDeclaredConstructor();
for(Constructor c : cs){
//得到参数列表类类型
c.getParameterType();
}
五、方法的反射操作
(1)定义一个A类,并声明方法print()
Class A{
public void print(int a,int b){}
public void print(){}
}
(2)反射操作代码举例
//先获取类的类类型
A a = new A();
Class c = a.getClass();
//获取print(int,int)方法
//Method m = c.getMethod("print",new Class[]{int.class,int.class});
Method m = c.getMethod("print",int.class,int.class);
//方法反射操作,有返回值就返回具体值,没有就返回null
//Object o = m.invoke(a,new Object[]{10,20});
Object o = m.invoke(a,10,20);
//获取print()方法
//Method m2 = c.getMethod("print",new Class[]{});
Method m2 = c.getMethod("print");
//m2.invoke(a,new Object[]{});
m2.invoke(a);
六、拓展
Java中的泛型,是防止错误输入的,只有编译阶段有效,绕过编译就无效了
//可以通过方法的反射来操作,绕过编译
ArrayList<String> list = new ArrayList<String>();
Class c = list.getClass();
Method m = c.getMethod("add",Object.class);
m.invoke(list,100);