为什么要反射?
- 通过反射技术读取.class文件
- JVM底层用了大把的反射,获取你定义的类中的数据。SSM框架底层也用了大把反射
- 作用:可以获取定义到任何定义的信息(包括成员变量,成员方法,构造器等)并且可以操作类的字段,方法,构造器等部分
反射的使用
- 源码摘抄
public final Class<T> extends Objectimplements Serializable
- 反射Class类对象
-Class.forName("类的圈路径") -类名.class -对象.getClass()
- 常用方法
获得包名、类名 clazz.getPackage().getName()//包名 clazz.getSimpleName()//类名 clazz.getName()//完整类名
!!成员变量定义信息 getFields()//获得所有公开的成员变量,包括继承的变量 getDeclaredFields()//获得本类定义的成员变量,包括私有,不包括继承的变量 getField(变量名) getDeclaredField(变量名)
!!构造方法定义信息 getConstructor(参数类型列表)//获得公开的构造方法 getConstructors()//获得所有公开的构造方法 getDeclaredConstructors()//获得所有构造方法,包括私有 getDeclaredConstructor(int.class, String.class)
方法定义信息 getMethods()//获得所有可见的方法,包括继承的方法 getMethod(方法名,参数类型列表) getDeclaredMethods()//获得本类定义的方法,包括私有,不包括继承的方法 getDeclaredMethod(方法名, int.class, String.class)
反射新建实例 c.newInstance();//执行无参构造 c.newInstance(6, "abc");//执行有参构造 c.getConstructor(int.class, String.class); //执行含参构造,获取构造方法
反射调用成员变量 c.getDeclaredField(变量名); //获取变量 c.setAccessible(true); //使私有成员允许访问 f.set(实例, 值); //为指定实例的变量赋值,静态变量,第一参数给 null f.get(实例); //访问指定实例的变量的值,静态变量,第一参数给 null
反射调用成员方法 获取方法 Method m = c.getDeclaredMethod(方法名, 参数类型列表); m.setAccessible(true) ;//使私有方法允许被调用 m.invoke(实例, 参数数据) ;//让指定的实例来执行该方法
测试public class Student { //提供构造 public Student() {} public Student(String name, int age) { this.name = name; this.age = age; } //提供属性 String name; int age; //提供方法 public void coding() { System.out.println("coding..."); } }
获取Class对象 //获取Class对象 @Test //测试方式:选中方法名-右键-Run as-Junit Test public void classTest() throws Exception { //?是泛型里的通配符,可以代表一切类型 Class<?> c = Class.forName("cn.tedu.reflection.Student");//参数是类的全路径--包名.类名 Class<?> c2 = Student.class; Student s = new Student(); Class<?> c3 = s.getClass(); System.out.println(c); System.out.println(c2); System.out.println(c3); }
获取构造方法 @Test //获取构造方法 public void consTest() throws Exception { //1,获取Class对象 ctrl 1自动补齐左面 Class<?> clazz = Class.forName("cn.tedu.reflection.Student"); //2,获取所有构造方法 Constructor<?>[] cs = clazz.getConstructors(); for (Constructor<?> c : cs) { Class<?>[] ps = c.getParameterTypes();//获取构造方法的参数 System.out.println( Arrays.toString(ps) ); //获取构造方法名称cn.tedu.reflection.Student System.out.println( c.getName() ); } }
获取成员方法 @Test //获取成员方法 public void methodTest() throws Exception { //1,获取Class对象 Class<?> clazz = Student.class; //2,获取所有 公共的 成员方法 Method[] ms = clazz.getMethods(); for (Method m : ms) { System.out.println( m.getName() );//包括继承自Object的所有方法 Class<?>[] ps = m.getParameterTypes();//获取方法的参数 System.out.println( Arrays.toString(ps) ); } }
获取成员变量 -- 要求:变量都是公共的!! @Test public void filedTest() throws Exception { //1,创建Class对象 //new Student() 这个对象没名字了,匿名对象 Class<?> clazz =new Student().getClass(); //2,获取 公共的 成员变量 !! Field[] fs = clazz.getFields(); for (Field f : fs) { System.out.println( f.getName() );//获取属性名 System.out.println( f.getType().getName() );//获取类型 } }
创建对象 @Test//创建对象 public void objectTest() throws Exception { //1,创建Class对象 Class<?> clazz = Student.class; //2,创建对象 Object object = clazz.newInstance();//用无参构造 System.out.println(object); //指定要用哪个含参构造 -- 参数是字节码对象的类型 Constructor<?> c = clazz.getConstructor(String.class,int.class); Object object2 = c.newInstance("jack",20);//用含参构造 System.out.println(object2);//Student [name=jack, age=20] }
暴力反射–就是反射类的私有数据:获取私有属性 @Test //反射私有属性 public void fieldTest() throws Exception { //1,创建Class对象 Class<?> clazz = Person.class; //2,反射 一个 私有属性 Field field = clazz.getDeclaredField("name"); System.out.println(field.getType().getName());//获取属性的类型 //设置私有属性的值 Object obj = clazz.newInstance(); field.setAccessible(true);//设置私有可见!!java.lang.IllegalAccessException: //set(m,n)-m是你要给哪个对象设置值,n是要给对象的指定属性设置什么值 field.set(obj, "肉丝"); System.out.println(field.get(obj));//查看值 //3、反射 所有 私有属性 Field[] fs = clazz.getDeclaredFields(); for (Field f : fs) { System.out.println(f.getType().getName());//属性的类型 System.out.println(f.getName());//属性的名字 f.setAccessible(true);//设置私有可见 Object o = clazz.newInstance(); System.out.println( f.get(o) +"===");//获取属性值 } }
获取私有方法 @Test public void methodTest() throws Exception { //1,创建Class对象 Class<?> clazz = Person.class; //2,获取 一个 私有方法 Method method = clazz.getDeclaredMethod("test", null); Class<?>[] ps = method.getParameterTypes(); System.out.println( Arrays.toString(ps) ); //3,执行方法 //invoke(m,n)--m是要执行哪个对象的方法 n是方法需要的参数 Object obj = clazz.newInstance(); method.setAccessible(true);//设置私有可见 method.invoke(obj, null); //4,获取 所有 私有方法 -- 2min Method[] ms = clazz.getDeclaredMethods(); for (Method m : ms) { Class<?>[] cs =m.getParameterTypes(); System.out.println( Arrays.toString(cs) ); //执行方法 Object o = clazz.newInstance(); m.setAccessible(true);//设置隐私可见 //?先获取到想要执行的方法 // m.invoke(o, null);必须要先指定要执行哪个方法 } }