java反射机制学习
Java反射技术
反射的核心思想
所谓的反射就是将一个类中的各个成员映射成相对应的JAVA类型
反射核心思想图
反射的目的
1.传递一个实体类---à装换成Map 2.将Map转换成一个实体类 |
1. 获取字节码文件的三种方式
a) Java类的组成部分 1. 每个类都有一个package 2. 每个类都有一个类名 3. 会有构造方法 4. 类中可以有属性 5. 可以有普通的方法 b) Class类是反射的根基(是作者为我们提供一个可以描述JAVA文件的类,Class类型的对象可以代表某一个类的字节码文件) |
2. 如何获取一个类的字节码文件(也就是Class对象)
1) 通过某一个类类名.class publicclass TestDome { @Test publicvoid test(){ //此处的c1代表的是User这个类的字节码文件,此处的Class是一个数据类型,c1就是这个类型的对象 Class c1=User.class; Class c2=Tree.class; System.out.print(c1); System.out.print(c2); } 2) 通过某一个Class.forName(“某个类的全路径”); Class c3=Class.forName("com.fanshe.test.Tree"); 3) 通过某一个对象名.getClass(); User user=new User(); Class c4=user.getClass(); |
3. 通过反射创建对象
4. 创建对象时一定会调用构造方法,因此需要通过反射先获取字节码文件(反射的根基),然后通过字节码来获取指定的构造方法-------再通过构造器创建对象 获取所有的构造方法:(获取某一个类中所有的构造方法【getConstructors()】) @Test publicvoid test1() throws ClassNotFoundException{//异常是字节码类文件找不到异常 //spring的IOC:控制反转--就是将某一个类的对象创建过程交给spring容器 //<bean id="xx" calss="com.fanshe.test.Tree"></bean> //1.获取字节码文件 Class calssuser=Class.forName("com.fanshe.test.User"); //所谓的反射就是将一个类中的各个成员映射成相对应的java类型 //2.需要创建一个对象(创建对象是一定要调用构造方法的) //调用User类中的无惨构造方法创建对象 Constructor[] userconstors=calssuser.getConstructors(); for (Constructor constructor : userconstors) { System.out.println(constructor); } } 获取指定的构造方法:(通过指定参数类型来获取某一具体的构造方法【getConstructors()】) @Test publicvoid test2() throws Exception{ //通过字节码文件获取指定构造方法--无参数 Class calssuser=Class.forName("com.fanshe.test.User"); Constructor constructor1=calssuser.getConstructor(); System.out.println(constructor1); //通过字节码文件获取指定构造方法--有参数 Constructor constructor2=calssuser.getConstructor(String.class,int.class); System.out.println(constructor2); } 通过无惨构造函数创建对象 @Test publicvoid test3() throws Exception{ //通过字节码文件获取指定构造方法--无参数 Class calssuser=Class.forName("com.fanshe.test.User"); Constructor constructor1=calssuser.getConstructor(); User user=(User) constructor1.newInstance(); System.out.println(user); } |
4.反射的效率问题
反射的创建对象要比传统的创建对象方式效率低很多
5. 通过反射来获取某一实体类中属性字段
a) 通过反射获取publicprotected,默认访问修饰符修饰字段
@Test publicvoid test() throws Exception{ //1.创建一个对象 Class userclass=User.class; User user=(User)userclass.getConstructor().newInstance(); //2.获取user这个类中的属性字段 Field[] field=userclass.getDeclaredFields(); for (Field field2 : field) { System.out.println(field2); } } |
b) 通过反射获取属性字段的访问修饰符
@Test publicvoid test2() throws Exception{ Class userclass=User2.class; User2 user=(User2)userclass.getConstructor().newInstance(); Field field=userclass.getDeclaredField("age"); int mod=field.getModifiers(); System.out.print("字段的访问修饰符是"+mod); /** * 注-- * 0--代表的是默认的 * 1--代表的是public * 2--代表的是private * 4--代表的是protected */ } |
c) 通过暴力反射获取private修饰过的属性字段的值(私有的)
/** * 通过暴力反射获取属性字段的值 * @throws Exception */ @Test publicvoid test3() throws Exception{ Class userclass=User2.class; User2 user=(User2)userclass.getConstructor().newInstance(); Field field=userclass.getDeclaredField("age"); field.setAccessible(true);//设置访问修饰符的可见性(暴力反射) Object obj=field.get(user); System.out.println(obj); } |
d) 通过反射修改指定属性字段的值
@Test publicvoid test3() throws Exception { Class userclass = User2.class; User2 user = (User2) userclass.getConstructor().newInstance(); Field field = userclass.getDeclaredField("age"); field.setAccessible(true);// 设置访问修饰符的可见性 Object obj = field.get(user);// get方法获取指定属性字段的值 System.out.println("被修改前的值是"+obj); field.set(user, 222);//set方法修改指定属性字段的值(注-user类中要有toString方法) System.out.println("被修改后的值" + user); } |
通过反射调用方法
1. 通过反射获取所有的方法
@Test publicvoid test4() throws Exception{ //通过反射调用方法 Class userclass = User2.class; Method[] mh=userclass.getMethods(); for (Method method : mh) { System.out.println(method); } |
通过反射获取指定的方法
@Test publicvoid test5() throws Exception{ //通过反射调用指定的方法 Class<User2> userclass = User2.class; User2 user = (User2) userclass.getConstructor().newInstance(); //获取user类中的tostring方法--无参 Method mo=userclass.getMethod("tostring"); mo.invoke(user);
} @Test publicvoid test6() throws Exception{ //通过反射调用指定的方法 Class<User2> userclass = User2.class; User2 user = (User2) userclass.getConstructor().newInstance(); //获取user类中的tostring方法--有参 Method mo=userclass.getMethod("tostring",int.class); mo.invoke(user,26);
} |
打包JAR包的方法—鼠标右键单击项目—Export—java—JAR file—选择保存的位置—最后OK(apache提供一个jar工具,将map装换成实体类,将实体类装换成map-工具名为commons-beanutils.jar)