A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© fashionkillyou 中级黑马   /  2017-10-30 14:45  /  963 人查看  /  8 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

19.1 反射介绍
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
对于任意一个对象,都能够调用它的任意一个方法
这种动态获取的以及动态调用对象的方法的功能称为java语言的反射机制
(我理解为就是在运行时,可以去获取当前项目中的所有的.class文件,然后去使用它的方法) 就是在运行时主动的获取对象
19.1.1获取字节码文件的三种方法准备类:
[Java] 纯文本查看 复制代码
public class FuLei {
	private String name;
	public int age;
	private String gender;
	public FuLei() {}
	private void ss(int a){
		System.out.println(a);
	}
	public FuLei(String name, int age, String gender) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	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;
	}
	@Override
	public String toString() {
		return "FuLei [name=" + name + ", age=" + age + ", gender=" + gender + "]";
	}
	public void method(){
		System.out.println("我是父类的方法");
	}
}



1、通过 对象名.getClass()方法获取
FuLei f =  new FuLei();
Class<? extends FuLei> class1 = f.getClass();
2、通过 类名.class属性来获取
System.out.println(FuLei.class);
3、通过 Class.forName(类的全名) ------类的全名是  包名.类名
Class<?> forName = Class.forName("com.test01.FuLei");//为了防止传入错误的类名此处将会抛出异常  ClassNotFoundException
19.1.2 通过获取的构造创建对象
字节码对象是什么?如何获取?
newInstance()新实例化对象方法,使用时一定要和获取构造器时的参数保持一致
getConstructor()方法返回的是一个字节码对象,之后的获取方法和属性的方法都是返回的相应的对象
//关于字节码对象,什么是字节码对象?如何获取?
                //首先要获取字节码
                //这里利用第一种方式获取了字节码文件
                Class<?> forName = Class.forName("com.test01.FuLei");
                //获取了无参构造,方法一,通过forName.getConstructor()得到无参构造的对象,然后调用无参构造的对象来调用newInstance()方法
//                Constructor<?> constructor = forName.getConstructor();
//                Object newInstance1 = constructor.newInstance();
                //方法二、根据无参构造进行实例化对象      newInstance()新实例化对象,只能创建无参构造来创建对象
                Object newInstance = forName.newInstance();
                System.out.println(newInstance);
                //根据有参构造进行实例化对象
                Constructor<?> constructor2 = forName.getConstructor(String.class,int.class);//参数是传的类型的字节码文件
                Object newInstance2 = constructor2.newInstance("刘欣明",25);
                System.out.println(newInstance2);
19.1.3 反射操作公共成员变量19.1.3.1反射public成员变量
注意:这里只能获取被public修饰的成员
通过反射运行public变量流程
1. 通过反射获取该类的字节码对象
Class clazz = Class.forName("com.heima.Person");
2. 创建该类对象
Object p = clazz.newInstance();
3. 获取该类中需要操作的字段(成员变量)
getField(String name) --> 方法传入字段的名称.
注意: 此方法只能获取公共的字段
Field f = clazz.getField("age");
4. 通过字段对象中的方法修改属性值
void set(Object obj, Object value)  --> 参数1): 要修改那个对象中的字段, 参数2): 将字段修改为什么值.
f.set(p, 23);
代码演示:
Class<?> forName = Class.forName("com.test01.FuLei");
                Object fu = forName.newInstance();
                Field age = forName.getField("age");
                Field name = forName.getField("name");
                name.set(fu, "刘欣明");
                age.set(fu, 25);
                System.out.println(age);//public int com.test01.FuLei.age
                System.out.println(fu);//FuLei [name=刘欣明
                Object age2 = age.get(fu);
                Object name2 = name.get(fu);
                System.out.println(age2);//25
                System.out.println(name2);//刘欣明
方法总结:
通过反射获取成员变量并使用  
                     Field[] getFields()              --> 返回该类所有(公共)的字段
                     Field getField(String name)      --> 返回指定名称字段
            
                    Field[] getDeclaredFields()      --> 暴力反射获取所有字段(包括私有)
                    Field getDeclaredField(String name) --> 暴力反射获取指定名称字段
              Field:
                      Object get(Object obj)          --> Field对象调用, 返回传入对象的具体字段
                      void set(Object obj, Object value) -->  Field对象调用
                                                        参数1: 要修改的对象
                                                        参数2: 将此对象的字段修改为什么值.
19.1.3.2反射private成员变量
反射private属性执行流程
1. 获取学生类字节码对象
2. 获取学生对象
3. 通过getDeclaredField方法获取私有字段
4. 通过setAccessiblejvm不检查权限
5. 通过set方法设置对象为具体的值
Class<?> forName = Class.forName("com.test01.FuLei");//获取字节码文件
                Object fu = forName.newInstance();//获取实例对象
                Field gender = forName.getDeclaredField("gender");//获取私有的成员变量
                gender.setAccessible(true);//暴力反射
                gender.set(fu, "");//设置值
                System.out.println(fu);//FuLei [name=null, age=0, gender=
                System.out.println(gender);//private java.lang.String com.test01.FuLei.gender
                Object xin = gender.get(fu);
                System.out.println(xin);//
19.1.3.3 反射获取方法执行流程
反射public方法执行流程
1. 获取学生类字节码对象
2. 反射手段创建学生对象
3. 调用getMethod方法获取Method对象, 方法形参接受方法的名字
4. 调用Method方法中的invoke()将方法运行
Class<?> Fu = Class.forName("com.test01.FuLei");//字节码文件
                Object f = Fu.newInstance();//实例化对象
                //无参无返回值
                Method method = Fu.getMethod("method");
                method.invoke(f);//调用方法
                //有参无返回值的方法
                Method method2 = Fu.getMethod("setName", String.class);
                method2.invoke(f, "lxm");//调用方法
                System.out.println(f);
19.2 JavaBean
/*
* JavaBean:用于封装数据
*                 类使用公共进行修饰
*                 提供私有修饰的成员变量
*                 为成员变量提供公共gettersetter方法
*                 提供公共无参的构造
*                 实现序列号接口
*
*/
19.3BeanUtils的常用方法
static void    setProperty(Object bean, String name, Object value)
static String getProperty(Object bean, String name)
static void    populate(Object bean, Map properties)
       
        setProperty  用来给对象中的属性赋值(了解)
                参数1: 需要设置属性的对象
                参数2: 需要修改的属性名称
                参数3: 需要修改的具体元素       
       
        getProperty 用来获取对象中的属性(了解)
                参数1: 要获取的javaBean对象
                参数2: 对象中的哪个属性
               
        Populate 用来给对象中的属性赋值(掌握)
                参数1: 要设置属性的对象
                参数2: 将属性以Map集合的形式传入
                                        Key : 属性的名称
                                        Value:  属性具体的值
BeanUtils setPropertygetProperty方法的底层并不是直接操作成员变量,而是操作成员变量有关的setget方法
BeanUtils populate(javabean,map);
//方法setProperty()
        public static void setProperty(Object bean, String name,Object value) throws ReflectiveOperationException{
                //通过反射获取字节码
                Class clazz = bean.getClass();
                //获取相应的属性对象
                Field f = clazz.getDeclaredField(name);
                //设置权限
                f.setAccessible(true);
                //赋值
                f.set(bean, value);
        }
        //方法getProperty()
        public static String getProperty(Object bean, String name) throws ReflectiveOperationException{
                //获取字节码对象
                Class clazz = bean.getClass();
                //获取属性的对象
                Field f = clazz.getDeclaredField(name);
                f.setAccessible(true);
                Object obj = f.get(bean);
                return obj.toString();
        }
        //方法 populate()
        public static void populate(Object bean,Map map) throws ReflectiveOperationException{
                //根据map里面的键值对的key来获取bean类中的属性,没有属性的话
                Class<? extends Object> c = bean.getClass();
               
                Set keys = map.keySet();
                for (Object key : keys) {
                        try{
                                //根据key获取value
                                Object value = map.get(key);
                                //得到属性的对象
                                Field f = c.getDeclaredField(key.toString());
                                //设置权限
                                f.setAccessible(true);
                                //赋值
                                f.set(bean, value);
                        }catch(NoSuchFieldException e){
                                e.printStackTrace();
                        }
                }

8 个回复

正序浏览
battlexing 发表于 2017-11-1 10:10
那么反射到底是个啥呢

就是在运行时获得类和他的对象,可以通过反射获得类的成员属性和方法
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报 1 0
那么反射到底是个啥呢
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
丶唯萌Pro 发表于 2017-10-31 22:55
姐姐,你咋这么棒吗?

妹妹也很厉害的
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
姐姐,你咋这么棒吗?
回复 使用道具 举报
heimalala 发表于 2017-10-30 17:29
受教了

相互学习!好好学习,天天向上!
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
播妞 发表于 2017-10-30 15:11
快找播妞兑换礼品去qq3414556270

啥礼品?
来自宇宙超级黑马专属安卓客户端来自宇宙超级黑马专属安卓客户端
回复 使用道具 举报
heimalala 来自手机 中级黑马 2017-10-30 17:29:08
藤椅
受教了
回复 使用道具 举报
播妞 程序媛 2017-10-30 15:11:01
沙发
快找播妞兑换礼品去qq3414556270
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马