无所不能的反射

反射

类加载的区别

我们来看以下这张图,
图中的RTTI方式,我们编写完java代码就进行编译,即在编译器我们就生成了class文件,这个过程就是我们常规的对一个对象的创建过程,在运行期我们再将其加载到内存中,进行运作:Animal animal = new Dog();即我们在编译器的时候就已经确定了子类对象到底具体是什么了

图中我们的反射在编译器没有确定什么东西,在运行期我们就可以动态的确定一个Animal对象是一个Dog还是Cat
在这里插入图片描述

JVM类加载流程和内存结构

我们编写的java文件在类编译器中会编译为class文件,我们下图中cafe babe这份文件(包含类的所有信息)。然后我们的ClassLoader将文件load到内存中,经过加载、验证、准备、解析、初始化这些阶段后,加载进内存之后我们就会对这个文件进行一个内存的管理
在这里插入图片描述

Class文件包含的内容

在这里插入图片描述

生成对象的步骤

横线以上其实就是我们常用到的生成对象(编译期),横线以下就是我们用到的反射方式进行创建对象(运行期),二者的共同点都是从构造函数进行创建对象。
在这里插入图片描述

获取Class类实例的三种方式

同一个对象的class对象只有一个,所以无论通过哪种方式创建,他们的对象都是同一个

@Test
public void test() throws Throwable{
    // 方式一  类.class
    Class personClazz = Person.class;

    // 方式二  实例.getClass()
    Person person = new Person();
    Class personClazz1 = person.getClass();

    // 方式三  Class.forName("类的全路径")
    Class personClazz2 = Class.forName("com.reflect.Person");

    System.out.println(personClazz == personClazz1);
    System.out.println(personClazz == personClazz2);
}

通过反射创建对象

/**
* // 无参数
* <bean id="person" class="com.muse.reflect.Person" />
*
* // 有参数
* <bean id="person" class="com.muse.reflect.Person" >
*    <constructor-arg index="0" type="java.lang.String" value="muse"/>
* </bean>
*
*/
@Test
public void test2() throws Throwable{
   /** 首先:获得Person的字节码 */
   Class personClazz = Class.forName("com.reflect.Person");

   /** 其次:通过Class对象,创建构造方法对象 */
   Constructor constructor1 = personClazz.getConstructor(String.class, Integer.class, Byte.class,Boolean.class); // 初始化有参构造方法对象
   Constructor constructor = personClazz.getConstructor(); // 初始化无参构造方法

   /** 最后:通过构造方法创建对象 */
   // 调用无参数构造方法创建Person对象
   Person person = (Person) constructor.newInstance();
   person.setName("ironMan");
   System.out.println("person=" + person);

   // 调用有参数构造方法创建Person对象
   Person person1 = (Person) constructor1.newInstance("ironMan", 10, (byte) 1, true);
   System.out.println("person1=" + person1);
}

反射的使用

获得属性

/**
 * public属性的
 */
@Test
public void test3() throws Throwable{
    // 第一步:获得Class
    Class personClazz = Person.class;

    // 第二步:获得构造方法
    Constructor<Person> constructor = personClazz.getConstructor();
    Person person = constructor.newInstance();

    // 第三步:通过Class对象,获得Field对象
    Field nameField = personClazz.getField("name");

    // 第四步:操作Field,获得属性值
    String name = String.valueOf(nameField.get(person));

    System.out.println(name);
}

获得私有属性

没有sexField.setAccessible(true);这句代码的话,会提示无权访问private属性

/**
 * private
 */
@Test
public void test4() throws Throwable{
    // 第一步:获得Class
    Class personClazz = Person.class;

    // 第二步:获得构造方法
    Constructor<Person> constructor = personClazz.getConstructor();
    Person person = constructor.newInstance();

    // 第三步:通过Class对象,获得Field对象
    Field sexField = personClazz.getDeclaredField("sex");
    sexField.setAccessible(true);

    // 第四步:操作Field,获得属性值
    System.out.println(sexField.get(person));
}

获得public属性值

通过反射获得类的public属性值

/**
* getField 只能获取public的,包括从父类继承来的字段。
* getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
*/
@Test
public void getPublicField() throws Throwable {
   /** 首先:获得Person的字节码 */
   Class personClazz = Person.class;
   
   /** 其次:获得Person对象(由于非静态非private的属性,访问使用 对象.属性方式访问,所以反射必须先获得对象实例)*/
   Person person = (Person) personClazz.getConstructor().newInstance();

   /** 第三:通过Class对象,获得Field对象 */
   Field nameField = personClazz.getField("name");
   // Field nameField = personClazz.getDeclaredField("name");  使用getDeclaredField也是ok的。

   /**
    * Field.toString();
    * --------------------------------------------------------------------
    * public String toString() {
	*     int mod = getModifiers();
	*     return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
	*       + getType().getTypeName() + " "
	*       + getDeclaringClass().getTypeName() + "."
	*       + getName());
    * }
    *
    * 【Field的重要方法】
    * System.out.println("获取字段的类型:" + nameField.getType());
    * System.out.println("获取字段的名字:" + nameField.getName());
    * System.out.println("获取字段的访问修饰符:" + Modifier.toString(nameField.getModifiers()));
    * System.out.println("获取字段所在类的全路径:" + nameField.getDeclaringClass().getName());
    */
   System.out.println(nameField); // protected java.lang.Integer com.Person.name

   /** 最后:获取字段的类型 */
   String name = String.valueOf(nameField.get(person));
   System.out.println(name);
}

获得private属性

/**
* 获得private属性
* @throws Throwable
*/
@Test
public void getPrivateField() throws Throwable {
   /** 首先:获得Person的字节码 */
   Class personClazz = Person.class;

   /** 其次:获得Person对象(由于非静态非private的属性,访问使用 对象.属性方式访问,所以反射必须先获得对象实例)*/
   Person person = (Person) personClazz.getConstructor().newInstance();

   /** 第三:通过Class对象,获得Field对象 */
   // Field sexField = personClazz.getField("sex");  不能使用getField,否则报错:java.lang.NoSuchFieldException: sex
   Field sexField = personClazz.getDeclaredField("sex");
   sexField.setAccessible(true); // 必须设置为true

   /** 最后:获取字段的类型 */
   Byte sex = (Byte) sexField.get(person);
   System.out.println(sex);
}

获得protected属性

/**
 * 获得protected属性
 *
 * @throws Throwable
 */
@Test
public void getProtectedField() throws Throwable {
    /** 首先:获得Person的字节码 */
    Class personClazz = Person.class;

    /** 其次:获得Person对象(由于非静态非private的属性,访问使用 对象.属性方式访问,所以反射必须先获得对象实例)*/
    Person person = (Person) personClazz.getConstructor().newInstance();

    /** 第三:通过Class对象,获得Field对象 */
    Field ageField = personClazz.getDeclaredField("age");
    ageField.setAccessible(true); // 必须设置为true,如果不设置,则报错:java.lang.IllegalAccessException: Class ReflectionTest can not access a member of class com.muse.Person with modifiers "protected"
    
    /** 最后:获取字段的类型 */
    Integer age = (Integer) ageField.get(person);
    System.out.println(age);
}

获得default属性

/**
 * 获得default属性
 *
 */
@Test
public void getDefaultField() throws Throwable {
    /** 首先:获得Person的字节码 */
    Class personClazz = Person.class;

    /** 其次:获得Person对象(由于非静态非private的属性,访问使用 对象.属性方式访问,所以反射必须先获得对象实例)*/
    Person person = (Person) personClazz.getConstructor().newInstance();

    /** 第三:通过Class对象,获得Field对象 */
    Field isMarriageField = personClazz.getDeclaredField("isMarriage");
    isMarriageField.setAccessible(true); // 必须设置为true,如果不设置,则报错:java.lang.IllegalAccessException: Class ReflectionTest can not access a member of class com.muse.Person with modifiers ""

    /** 最后:获取字段的类型 */
    Boolean isMarriage = (Boolean) isMarriageField.get(person);
    System.out.println(isMarriage);
}

反射的应用

采用反射机制来实现一个工具BeanUtils,可以将一个对象属性相同的值赋值给另一个对象

public static void convertor(Object originObj, Object targetObj) throws Throwable{
   // 第一步,获得class对象
   Class orginClazz = originObj.getClass();
   Class targetClazz = targetObj.getClass();

   // 第二步,获得Field
   Field[] orginFields =  orginClazz.getDeclaredFields();
   Field[] targetFields =  targetClazz.getDeclaredFields();

   // 第三步:赋值
   for (Field originField : orginFields) {
       for (Field targetField : targetFields) {
           if (originField.getName().equals(targetField.getName())) {
               originField.setAccessible(true);
               targetField.setAccessible(true);
               targetField.set(targetObj, originField.get(originObj));
           }
       }
   }
}
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 智慧社区背景与挑战 随着城市化的快速发展,社区面临健康、安全、邻里关系和服务质量等多方面的挑战。华为技术有限公司提出智慧社区解决方案,旨在通过先进的数字化技术应对这些问题,提升城市社区的生活质量。 2. 技术推动智慧社区发展 技术进步,特别是数字化、无线化、移动化和物联化,为城市社区的智慧化提供了可能。这些技术的应用不仅提高了社区的运行效率,也增强了居民的便利性和安全性。 3. 智慧社区的核心价值 智慧社区承载了智慧城市的核心价值,通过全面信息化处理,实现对城市各个方面的数字网络化管理、服务与决策功能,从而提升社会服务效率,整合社会服务资源。 4. 多层次、全方位的智慧社区服务 智慧社区通过构建和谐、温情、平安和健康四大社区模块,满足社区居民的多层次需求。这些服务模块包括社区医疗、安全监控、情感沟通和健康监测等。 5. 智慧社区技术框架 智慧社区技术框架强调统一平台的建设,设立数据中心,构建基础网络,并通过分层建设,实现平台能力及应用的可持续成长和扩展。 6. 感知统一平台与服务方案 感知统一平台是智慧社区的关键组成部分,通过统一的RFID身份识别和信息管理,实现社区服务的智能化和便捷化。同时,提供社区内外监控、紧急救助服务和便民服务等。 7. 健康社区的构建 健康社区模块专注于为居民提供健康管理服务,通过整合医疗资源和居民接入,实现远程医疗、慢性病管理和紧急救助等功能,推动医疗模式从治疗向预防转变。 8. 平安社区的安全保障 平安社区通过闭路电视监控、防盗报警和紧急求助等技术,保障社区居民的人身和财产安全,实现社区环境的实时监控和智能分析。 9. 温情社区的情感沟通 温情社区着重于建立社区居民间的情感联系,通过组织社区活动、一键呼叫服务和互帮互助平台,增强邻里间的交流和互助。 10. 和谐社区的资源整合 和谐社区作为社会资源的整合协调者,通过统一接入和身份识别,实现社区信息和服务的便捷获取,提升居民生活质量,促进社区和谐。
IDM全称Internet Download Manager(互联网下载管理器),是一款用于加速和管理下载任务的神器级软件。它可以稳定、快速地下载各种文件,提供了多线程下载、断点续传和安全性保障等功能,使得用户能够更加方便地下载所需的内容。 首先,IDM通过多线程技术,能够将一个下载任务分成多个线程同时下载,从而大幅度提升下载速度。无论是下载视频、音乐、文档还是软件等,IDM都能够以最快的速度将文件下载到本地,节省了用户的时间。 其次,IDM支持断点续传功能,即使因为网络中断、电脑关机等原因导致下载中断,用户不必从头再次下载,而是可以将下载任务从中断处继续进行,节省了用户的流量和时间成本。 此外,IDM还内置了智能下载逻辑和计划功能,可以根据网络状况和用户设定进行智能分配带宽,避免占用过多资源而影响其他网络活动。同时,用户还可以根据个人需求设置定时下载任务,让IDM在特定时间自动开始下载或关闭,提高了用户的使用便利性。 最重要的是,IDM不仅支持常见的HTTP、HTTPS和FTP协议,还能够有效地与各种主流浏览器无缝整合,实现一键下载。用户只需在所需下载的文件链接上右键点击,选择“IDM下载链接”,即可调用IDM进行高速下载,大大简化了文件获取过程。 综上所述,IDM不仅速度快、稳定性高,而且具有多种实用功能,是一款无所不能的下载神器,能够满足各类用户的下载需求。无论是下载工作文档、观看在线视频还是获取软件安装包,IDM都能够为用户提供快速、便捷的下载体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值