src==> 源文件存放位置 bin==> bean 文件 _____________________________________________________________ ============================================================= ++++++++++++++++++++++++ 反射 笔记 +++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ _____________________________________________________________ --> 面向对象: 万物皆对象 --> java类 : 类的组成部分 ( 1 )每个类都有一个package ( 2 )每个类有一个类名 ( 3 )构造方法 ( 4 )属性 ( 5 )普通方法 ....... 静态方法 未包括 ============================================================= ---> 反射的根基 : java 开发者为我们提供了一个类来描述 java 文件 ,这个类为Class 同时,Class 类型对应的对象可以代表某一个某一个类的字节码文件 public class Class { ...... } 对象代表字节码文件 字节码文件类型 ===> . class ================================== ---> 如何获取某一类的字节码文件? ====> 获取一个类的对象 -------------------------------------------------------- [ 注: 反射不能 new 出来 , 没有 new ] 三种方式获取: --> 通过类名.class --> 类名.forName("某个类的全路径") --> 对象名 .getClass( ) [ - 点不能丢 - ] --------------------------------------------------------- @Test //获取User的字节码文件 public void ReflectionTest1() throws ClassNotFoundException { //通过类名获取字节码文件 Class userClass = User.class; <---------- 第一种 //通过.forName获取字节码文件 Class u = Class.forName("User"); <---------- 第二种 //通过.getClass 获取 User user = new User(); Class get = user.getClass(); <---------- 第三种 //以上三者获取的是同一个字节码文件 , sout 输出 true // 注意 第三种获取的方式需要实例化对象,通过对象的.getClass方法获取 System.out.println(u==userClass); System.out.println(u==get); } ---------------------------------------------------------- 所有类的底层都是字节码===> 二进制文件 ---------------------------------------------------------- * 通过反射创建对象 * 所谓的反射,将一个类中的 各个成员 映射 成 相对应的 java类型 * ================================================================== * 各个成员: 包括 { 包 --> package, 构造器 ---> Contructor , 属性字段 ---> Field , 普通方法 ----> Method } * ================================================================== * * spring 机制 : * <bean id = " xx " class = " com.xsh.User " ></bean> * ====> 通过 Class.forName( " 类的全路径 ") 获取 字节码文件 * 以字节码文件为纽带,创建实例. * --------------------------------------------------------- @Test public void ReflectionTest2() throws Exception { // 1/获取字节码文件 Class userClass = Class.forName("User"); //2/需要创建一个对象, ===> 创建对象一定需要调用构造方法 调用类中的无参构造方法来创建构造对象 Constructor[] constructors = userClass.getConstructors(); for (Constructor constructor : constructors ) { ====> System.out.println(constructor); ====> for循环打印所以构造方法 } ====> //通过字节码获取无参构造方法 Constructor constructor =userClass.getConstructor(); //通过无参构造方法,创建对象 User u = (User) constructor.newInstance(); System.out.println(u); ===> 打印出对象: 证明通过映射成功创建对象 //通过字节码获取有参构造方法 Constructor constructor1 = userClass.getConstructor(String.class,int.class); User uu = (User) constructor1.newInstance("张三",21); ===> 这里是赋值给通过映射创建的对象 System.out.println(uu); ===> 打印出对象: 证明通过映射成功创建对象 } ------------------------------------------------------------ 反射对象和传统对象效率相比: 反射的效率比传统方式低很多 ----> 创建一百个对象速度相比,低至 10~ 20 倍 我自己测是这样的 , 总结就是低很多...量越大,效率越低 ------------------------------------------------------------ ================================================================================================================== public class User { private String name = "张三李四"; //姓名 int age = 26; //年龄 protected float weight = 60.5F; //体重 public float height = 180.5F; //身高 构造方法略过.... } ================================================================================================================== 1 / 在不给出任何接口的情况下( toString 方法也不给出 )如何获取到User类中私有属性的值 ? ====> 反射 ------------------------------------------------------------------------- * ================================================================== * 通过反射获取某一个实体对象的属性字段及其值 * 1/通过反射获取public.protect,默认修饰符修饰的属性字段和值 * 2/通过暴力反射获取 私有属性字段及其值 private 修饰的 * ================================================================== * 反射里将属性封装成了field类型 : * 修饰符 数据类型 属性名 * getFields() ===> 只能获取public修饰的属性 * getDeclaredFields ====> 获取除了私有的之外的三种修饰符修饰的字段 jdk 8 获取全部 ================================================================= @Test public void test() throws Exception { //创建一个对象 Class c = User.class; User user = (User) c.getConstructor().newInstance(); //获取user这个对象的属性字段 Field[] fields = c.getDeclaredFields(); for (Field s : fields ) { [ 这里仅仅是部分方法 仅供参考 ] System.out.println(s); } //获取指定字段的属性 [ 默认=> 0 public=>1 protected =>4 private =>2 ] Field field = c.getDeclaredField("weight"); System.out.println(field.getType()); //获取字段类型 System.out.println(field.getModifiers()); //返回修饰符的值 System.out.println(field.getName()); //获取字段名字 System.out.println(field.getDeclaringClass().getTypeName()); //获取属性类路径 } ================================================================= @Test public void test() throws Exception { //创建一个对象 Class c = User.class; User user = (User) c.getConstructor().newInstance(); //获取user这个对象的属性字段 Field[] fields = c.getDeclaredFields(); for (Field s : fields ) { // System.out.println(s); } //获取指定字段的属性 Field field = c.getDeclaredField("name"); System.out.println(field.getType()); //获取字段类型 System.out.println(field.getModifiers()); //返回修饰符的值 System.out.println(field.getName()); //获取字段名字 System.out.println(field.getDeclaringClass().getTypeName()); //获取属性类路径 //暴力反射 ==> 获取所有属性的值 如果某个属性被私有化,想要获取就需要通过暴力反射 field.setAccessible(true); Object o = field.get(user); System.out.println(o); //修改某字段值 field.set(user,"牛二刘三"); System.out.println(user); //修改成功 } ================================================================= ======================================================================================================================== [ 默认=> 0 public=>1 protected =>4 private =>2 ] 为什么没有3? 1Byte = 8 bit 字节 位 计算机底层 二进制 一个字节 ==> 8 位 计算机传输的时候每次最少是一个八位的字节 1==> 高电压 0==> 低电压 00000000 0 00000010 1*2^0 = 1 00000100 1*2^1 = 2 00001000 1*2^2 = 4 这样的传输效率最高 === > 所以没有 3 ! ========================================================================================================================
反射学习笔记(二) - - 暴力反射 - -
最新推荐文章于 2022-04-06 14:27:24 发布