【反射简单理解】

一、什么是RTTI

在java中,能让程序在运行时识别对象和类的信息的方法有两种,一种是传统的RTTI(Run-Time Type Identification)运行时类型类型信息识别,另一种是反射。
对于RTTI,它假设我们在编译时已经知道是哪种类型,反射是允许我们在运行时发现和使用类的信息。

二、什么是反射?

反射是指在运行过程中,任意一个类都能够知道这个类里的所有属性和方法,对任意一个对象都能够调用它的任意一个属性或方法,这种动态的获取信息和调用对象方法的功能就叫做反射。

三、类的加载流程

每一个类在编译后都会生成一个对应的以.class为后缀名的文件,在创建一个对象或使用类里面的静态成员时,就会加载这个类。每个类都会产生对应的class对象,在加载这个类时,类加载器首先会去检查这个类的class对象是否被加载过,若尚未加载,默认的类加载器就会根据类名查找对应的.class文件,将文件加载到JVM中,然后创建一个class对象,下一步会验证代码是否规范,并给一些静态成员分配空间,如果该类有超类,则对其初始化,并执行静态初始化器和静态初始化块。

在这里插入图片描述

四、利用反射动态创建对象

1、获取class对象的三种方式

创建一个Animal类

package edu.reflex.demo1.Animal

public class Animal {
	private String name;
	private String sex;
	private int age;
	public Animal(){
		
	}
	public Animal(String name, String sex, int age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Animal [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
}

1.1、通过Class.forName获取

//className必须是全路径名称;
//Class.forName()有异常:ClassNotFoundException
try {
	Class clazz = Class.forName("edu.reflex.demo1.Animal");
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}

1.2、通过类名.Class获取

/**
* 利用class属性获取字节码文件(类.class:需要输入一个明确的类,
* 任意一个类型都有一个静态的class属性)
*/
Class clazz = Animal.class;

1.3、通过对象名.getClass()获取

// 利用getClass()方法获取对象的class 对象
Animal animal = new Animal();
Class clazz = animal.getClass();

2、动态创建对象

2.1、使用newInstance()方法创建对象

// 通过newInstance()方法来创建对应类的实例
// 使用这个方法要求class对象对应的类必须要有默认构造器,
// 也就是无参构造方法
try {
	Object obj = clazz.newInstance();
} catch (InstantiationException e) {	
	e.printStackTrace();
} catch (IllegalAccessException e) {
	e.printStackTrace();
}

2.2、使用构造方法创建对象

// 使用Class对象获取指定的Constructor对象,调用Constructor对象的
// newInstance()方法来创建Class对象对应类的实例。这个方法可以使用Class
// 对象对应类的任意指定的构造器来创建实例
try {
	Constructor construct = clazz.getConstructor(String.class,String.class,int.class);
	Object obj = construct.newInstance("狗","公",3);
} catch (NoSuchMethodException e) {
	e.printStackTrace();
} catch (SecurityException e) {
	e.printStackTrace();
} catch (InstantiationException e) {
	e.printStackTrace();
} catch (IllegalAccessException e) {
	e.printStackTrace();
} catch (IllegalArgumentException e) {
	e.printStackTrace();
} catch (InvocationTargetException e) {
	e.printStackTrace();
}

五、利用反射调用方法

//获取class对象
Class clazz = Class.forName("edu.reflex.demo1.Animal");
//反射创建类的实例
Animal obj = (Animal) c1.newInstance();		
obj.setName("人");
//通过反射获取到method对象
Method m = c1.getMethod("getName");
//通过method对象的invoke方法调用方法
Object o = m.invoke(obj);
System.out.println(o);

六、动态操作属性(调用get,set方法)

获取属性:

//获取class对象
Class clazz = Class.forName("edu.etime.reflex.demo1.Animal");
//反射创建类的实例
Animal obj = (Animal) clazz .newInstance();	
//获取公有属性
Field[] fileds = clazz .getFields();
for(Field f :fileds){
	System.out.println("公有属性:"+f.getName());
	
}

Field[] fileds2 = clazz .getDeclaredFields();
for(Field f :fileds2){
	System.out.println("私有属性:"+f.getName());
}

给属性赋值:

Field[] fileds2 = clazz.getDeclaredFields();
for(Field f :fileds2){
	System.out.println("私有属性:"+f.getName());
	f.setAccessible(true);
	if(f.getType().equals(String.class)){
		f.set(obj, "123");
	}else if(f.getType().equals(int.class)){
		f.set(obj, 123);
	}
}
System.out.println(obj.toString());

调用get、set方法:

PropertyDescriptor p = new PropertyDescriptor("name",clazz);
//获取写方法
Method mset = p.getWriteMethod();
mset.invoke(obj, "你好");
//获取读方法
Method mget =  p.getReadMethod();
System.out.println(mget.invoke(obj));

或者

//或者(拼接一个get或则set方法的名称)
String fname = "name";
String mname = "get"+fname.substring(0,1).toUpperCase()+fname.substring(1);//getName
Method m = clazz.getMethod(mname);
System.out.println(m.invoke(obj));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值