一、反射的介绍

JAVA反射机制是在运行状态中,能够获取任意一个类的所有属性和方法,对于任意一个对象,都能够调用它的任意
一个方法。这种动态获取的以及动态调用对象的方法的功能称为java语言的反射机制。JAVA编译时是先获取到类,然
后才是类里边的属性和方法,而反射则和编译相反,他是先获取类里边的对象和方法然后在告诉他是哪个类里的。简单
来说, 就可以把.class文件比做动物的尸体, 而反射技术就是对尸体的一种解剖.通过反射技术, 我们可以拿到该字节码
文件中所有的东西, 例如成员变量, 成员方法, 构造方法, 而且还包括私有。想要反射首先要获取到程序的“尸体”也就
是.class文件。

二、字节码文件的获取

获取字节码对象有3种方式:
1、类名.class - 这是一个静态的属性, 只要知道类名, 就可以获取
2、对象名.getClass() - Object类里的getClass()方法,对象已经存在的情况下, 可以使用这种方式
3、Claire.forName("类的全类名(包名+类名)") - 通过Class类里的静态方法forName来获取节码对象
  举例:

 public static void main(String[] args) throws ClassNotFoundException {
// 通过Object的getClass()方法获取,必须要有对象
Student s = new Student();
Class clazz = s.getClass();
// 通过类名获取字节码对象
Class clazz2 = Student.class;
// 通过Class类里的静态方法forName来获取节码对象
Class clazz3 = Class.forName("com.fanshe.Student");
System.out.println(clazz == clazz2);
System.out.println(clazz == clazz3);
System.out.println(clazz); }

字节码文件其实就是描述.class文件的对象。

三、对构造方法的操作

*通过反射获取公有构造方法的两种方式:
1、返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法,可以获取无参构造也可以
根据传入的类型来匹配对应的构造方法:getConstructor(Class<?>... parameterTypes)
2、返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法:
                                                               getConstructors()
3、创建此 Class 对象所表示的类的一个新实例:
                                                               newInstance()

*暴力获取(可以获取全部权限的):
1、返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法:
                                 getDeclaredConstructor(Class<?>... parameterTypes)
2、返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法:
                                 getDeclaredConstructors()
  举例:

 public static void main(String[] args) throws ReflectiveOperationException {
// Class.forName()获取字节码对象
Class<?> forName = Class.forName("com.fanshe.Student");
// 获取所有公共构造方法
Constructor<?>[] constructors = forName.getConstructors();
// 遍历
for (Constructor<?> constructor : constructors) {
// 打印结果
System.out.println(constructor);
}
System.out.println("--------------------------------------");
// 暴力获取,可以获取所有的构造方法(包括私有的)
Constructor<?> c1 = forName.getDeclaredConstructor();
c1.setAccessible(true);
System.out.println(c1);
//获取有参构造
Constructor<?> c2 = forName.getConstructor(String.class, int.class);
System.out.println(c2);
}

四、对成员变量和方法的操作

*公有成员变量获取方法:
1、返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段:
                          getField(String name) - 参数为要返回的变量名
2、返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段:
                          getFields() - 参数为要返回的变量名

*任意成员变量获取方法:
1、返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段:
                          getDeclaredField(String name) - 参数为要返回的变量名
2、返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段:
                         getDeclaredFields() - 参数为要返回的变量名
 
    *获取公有的方法:
1、返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法:
                         getMethod(String name, Class<?>... parameterTypes) - name 方法名、parameterTypes 参数列表
2、返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口
声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法:
                         getMethods()

*暴力获取方法:
1、 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法:
                         getDeclaredMethod(String name, Class<?>... parameterTypes) - name 方法名、parameterTypes
参数列表
2、返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、
默认(包)访问和私有方法,但不包括继承的方法:
                        getDeclaredMethods()
    需要注意的是想要获取私有的变量或者方法时应使用AccessibleObject类里的setAccessible(boolean flag)方法 - 参数
值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问
检查。
    Constructor, Field, Method都是AccessibleObject的子类所以可以直接使用父类的setAccessible(boolean flag)方法。

**通过反射获得变量的流程:
1. 通过反射获取该类的字节码对象
2. 创建该类对象
3. 获取该类中需要操作的字段(成员变量) 
4. 通过字段对象中的方法修改属性值

**通过反射执行方法的流程
1. 通过反射获取该类的字节码对象
2. 创建该类对象
3. 调用getMethod方法获取Method对象, 方法形参接受方法的名字
4. 调用Method方法中的invoke()将方法运行
  举例:
*被反射的学生01类

 public class Student01 {
public String name;
private int age; public Student01() {
super();
// TODO Auto-generated constructor stub
} public Student01(String name, int age) {
super();
this.name = name;
this.age = age;
} public void name() {
System.out.println("测试"); } public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} private void mane1() {
System.out.println("这是个萌萌哒私有的"); } @Override
public String toString() {
return "Student01 [name=" + name + ", age=" + age + "]";
} }

*对学生01类进行反射

 public static void main(String[] args) throws ReflectiveOperationException {
// 获取字节码对象
Class<?> clazz = Class.forName("com.fanshe.Student01");
// 创建该类的对象
Object stu = clazz.newInstance();
// System.out.println(stu);
// 获取学生类的name变量
Field f1 = clazz.getField("name");
/*
* set将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
* 为stu对象里的name变量赋值
*/
f1.set(stu, "李四");
// get()返回指定对象上此 Field 表示的字段的值。
Object name = f1.get(stu);
// 暴力获取age字段
Field f2 = clazz.getDeclaredField("age");
System.out.println(f2);
// 让jvm不检查权限
f2.setAccessible(true);
// 为其赋值
f2.set(stu, 24);
// 获取stu对象的f2字段的值
Object age = f2.get(stu);
System.out.println(name);
System.out.println(age);
// 公有无参无返回值,name()
Method method = clazz.getMethod("name");
// 使用Method类的invoke方法执行name方法
method.invoke(stu);
// 公有代参无返回值,参数为String类型
Method m2 = clazz.getMethod("setName", String.class);
// 执行stu对象的setName方法,传入参数
m2.invoke(stu, "李晨宇");
// 公有无参有返回值
Method m3 = clazz.getMethod("getName");
// 返回值为invoke
Object invoke = m3.invoke(stu);
System.out.println(invoke);
// 私有
Method m4 = clazz.getDeclaredMethod("mane1");
// 让jvm不检查权限
m4.setAccessible(true);
// 执行stu对象的mane1方法
m4.invoke(stu);
}

需要注意的是,反射无参构造时被反射的类一定要有无参构造方法,默认生成的也算。
五、反射的应用

我们在开发的时候,由于要考虑到代码的重用性,就会用反射来处理一些问题。而JAVA的一些常用jar包和主流框架的配置
都用到了反射的原理,学习反射有助于我们对源码的阅读和理解。BeanUtils工具类(Apache开发的便于操作JavaBeen的工具类)
就用到了反射的方法。
  *BeanUtils的部分实现:

 public class MyBeanUtils {
//因为是工具类,不需要实例化。所以私有构造方法
private MyBeanUtils() {
super();
// TODO Auto-generated constructor stub
} /*
* 给对象中的属性赋值 传入类的对象类型,和要修改的属性的值不确定所以用Object类型,属性名用String类型
*/
public static void setProrerty(Object object, String name, Object values)
throws ReflectiveOperationException, SecurityException {
// 获取传入对象的字节码文件
Class clazz = object.getClass();
// 根据传入的属性获取Field对象,因为不确定属性的权限,用的暴力反射
Field field = clazz.getDeclaredField(name);
// 让jvm不检查权限
field.setAccessible(true);
// 为object对象里的name属性赋值
field.set(object, values); } // 获取对象中的属性
public static String getProrerty(Object object, String name)
throws ReflectiveOperationException, SecurityException {
// 获取传入对象的字节码文件
Class clazz = object.getClass();
// 根据传入的属性获取Field对象,因为不确定属性的权限,用的暴力反射
Field field = clazz.getDeclaredField(name);
// 让jvm不检查权限
field.setAccessible(true);
// 获取name属性的值
Object object2 = field.get(object);
// System.out.println(object);
// 将值返回
return object2.toString();
} // 给对象中的属性赋值(通过Map的方式),Map里key存的是属性名,value存的是要赋的值
public static void populat(Object object, Map map) throws ReflectiveOperationException, SecurityException {
// 获取传入对象的字节码文件
Class clazz = object.getClass();
// 返回此集合中的key集合
Set keySet = map.keySet();
// 遍历key
for (Object object2 : keySet) {
// 获得value值
Object value = map.get(object2);
try {
// 根据传入的key(属性)获取Field对象,因为不确定属性的权限,用的暴力反射
Field field = clazz.getDeclaredField(object2.toString());
// 让jvm不检查权限
field.setAccessible(true);
// 赋值
field.set(object, value);
} catch (NoSuchFieldException e) {
// 出现异常,给出友好型提示
System.out.println("Mdzz,属性都记不住");
}
}
}
}

*测试工具类:

 public static void main(String[] args) throws RuntimeException, ReflectiveOperationException {
// 创建学生01对象
Student01 s1 = new Student01();
// 使用MyBeanUtils工具类为学生01对象赋值
MyBeanUtils.setProrerty(s1, "name", "啦啦");
MyBeanUtils.setProrerty(s1, "age", 15);
// 使用MyBeanUtils工具类为学生01对象取值
String name = MyBeanUtils.getProrerty(s1, "name");
String age = MyBeanUtils.getProrerty(s1, "age");
// 打印出来
System.out.println(name);
System.out.println(age);
System.out.println("------------------------------------ ");
// 创建HashMap作为数据源
HashMap<String, Object> hashMap = new HashMap<>();
// 为HashMap赋值
hashMap.put("qqqqq", "大大的"); // 属性不存在会给出友好型提示
hashMap.put("name", "大大的");
hashMap.put("age", 110);
// 使用MyBeanUtils工具类为学生01对象赋值
MyBeanUtils.populat(s1, hashMap);
System.out.println(s1);
}

JAVA基础-反射的更多相关文章

  1. Java基础-反射(reflect)技术详解

    Java基础-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类加载器 1>.JVM 类加载机制  如下图所示,JVM类加载机制分为五个部分 ...

  2. Java基础——反射

    今天学到Java基础中的反反射.依照我学习后的个人理解呢,反射就是一套获取类.属性.方法等的工具吧.(其实,感觉学完反射后,有点像喝凉水,解渴但确实我也没体会出它有什么味道,我可能没有学到精髓吧.自己 ...

  3. Java基础反射(二)

    原文地址http://blog.csdn.net/sinat_38259539/article/details/71799078 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Cla ...

  4. java基础(反射,注解,多线程,juc)

    JAVA基础 java反射 class对象 三种方式获取class加载时对象 1.class.forName("全类名"):将字节码文件加载进内存,返回class对象 2.类名.c ...

  5. [java 基础]反射入门

    原文 概况 使用java的反射,可以让我们检查(或者修改)类,接口,字段,方法的特性.当你在编译期不知道他们的名字的时候非常有用. 除此之外,可以使用反射来创建实例,调用方法或者get/set 字段值 ...

  6. JAVA基础-反射机制

    什么是JAVA的反射机制 Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其 ...

  7. java基础-反射(细节)

    java面试题--java反射机制? Java反射机制的作用:1)在运行时判断任意一个对象所属的类.2)在运行时判断任意一个类所具有的成员变量和方法.3)在运行时任意调用一个对象的方法4)在运行时构造 ...

  8. Java基础—反射(转载)

    转载自: JAVA反射与注解 JAVA反射 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射机制是什么 反射 ...

  9. java基础——反射机制

    反射机制是什么 反射机制就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...

  10. Java基础—反射与代理(新手向)

    第1章 反射与代理 1.1 反射定义 一般情况下,需要一个功能的前提是遇到了某个问题,这里先列举一些问题,然后再通过反射是如何解决了这些问题,来引出反射的定义. 普通开发人员工作中最常见的问题:需要生 ...

随机推荐

  1. 团队作业8——第二次项目冲刺(Beta阶段)--5.21 second day

    团队作业8--第二次项目冲刺(Beta阶段)--5.21 second day Day two: 会议照片 项目进展 今天是beta冲刺的第二天,组长还在准备考试当中,我们继续做前端改进和后端安排,今 ...

  2. 201521123107 《Java程序设计》第2周学习总结

    第2周作业-Java基本语法与类库 1.本周学习总结 要点主要有: (1)String类 String类是本周的一个重点,String类的对象是不可变的,即String对象后就在内存中开辟了一个字符串 ...

  3. Swing-布局管理器之FlowLayout(流式布局)-入门

    FlowLayout应该是Swing布局管理器学习中最简单.最基础的一个.所谓流式,就是内部控件像水流一样,从前到后按顺序水平排列,直到达到容器的宽度时跳转到第二行.既然是水平排列,那么就存在三种基本 ...

  4. 【Alpha】——Fourth Scrum Meeting

    一.今日站立式会议照片 二.每个人的工作 成员 昨天已完成的工作 今天计划完成的工作 李永豪 完善添加功能 测试统计功能 郑靖涛 完善删除功能 着手编写报表设计 杨海亮 完善查找功能 协助编写统计功能 ...

  5. 201521123057 《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 2. 书面作业 注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图) 答: 面向对象 ...

  6. 201521123033《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  7. 通过Excel认识POI

    1.POI是什么 Apache POI - the Java API for Microsoft Documents,顾名思义,Apache的三方包,用来操作微软office文档的,多数时候用来操作e ...

  8. win10- *.msi 软件的安装,比如 SVN安装报2503,2502

    1, 以管理员身份打开cmd ,   C:\Windows\System32\cmd.exe 2,输入: msiexec /package "安装文件的全路径" 3,按下回车. 例 ...

  9. Java实现MD5加密_字符串加密_文件加密

    Java实现MD5加密,具体代码如下: package com.bstek.tools; import java.io.FileInputStream; import java.io.IOExcept ...

  10. JavaScript自动化构建工具入门----grunt、gulp、webpack

    蛮荒时代的程序员: 做项目的时候,会有大量的js 大量的css   需要合并压缩,大量时间需要用到合并压缩 在前端开发中会出现很多重复性无意义的劳动  自动化时代的程序员: 希望一切都可以自动完成  ...