反射加强

反射介绍

反射,一种计算机处理方式。是程序可以访问、检测和修改它本身状态或行为的一种能力。

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

Java反射常用API
在这里插入图片描述

在java.lang.reflect包下有三个类

在这里插入图片描述

优点:

1、反射提高了程序的灵活性和扩展性。

2、降低耦合性,提高自适应能力。

3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺点:
1、性能问题:使用反射基本上是一种解析操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。

2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

Class介绍

Java中的Class它可以代表任意的类或接口类型.

如何获取一个Class?

有三种方式:

  1. 如果持有一个对象,可以直接通过从Object类中继承的getClass方法获取

// 1.如果你得到一个类的对象
@Test
public void test1() {
User user = new User();
Class class1 = user.getClass(); // getClass方法是从Object类中继承
System.out.println(class1);
}

  1. 可以直接通过类包(接口)直接调用其属性.class获取

// 2.可以直接通过类名获取
@Test
public void test2() {
Class clazz = User.class;
System.out.println(clazz);
}

  1. 可以通过Class类中提供的forName方法获取

// 3.推荐使用的方案
@Test
public void test3() throws ClassNotFoundException {
Class clazz=Class.forName(“com.it.reflect.User”);
System.out.println(clazz);
}

为什么要获取Class对象?

对于我们学习反射,我们在操作中一般会获取类的成员 Constructor Field Method,但是要想获取这些对象,必须首先得到其Class,通过Class来获得其它对象

Constructor介绍

Constructor它描述的单个构造器,我们得到它就可以实例化对象.

问题:如何获取Constructor?
在这里插入图片描述

getConstructor它获取的是类的public构造

getConstructors它获取的是类的所有的public构造

在这里插入图片描述

以上两个方法不仅可以获取public,也可以获取其它权限的。

我们得到构造器,就可以实例化对象

在这里插入图片描述

如果不是public,那么我们需要通过AccessibleObject中的

在这里插入图片描述

来取消检查

Field介绍

Java.lang.reflect.Field它描述的属性对象。

关于Filed我们了解以下两个方面

  1. 如何获取一个Field

在这里插入图片描述

在这里插入图片描述

  1. Field的操作

    a. 对Field进行赋值
    在这里插入图片描述

b. 对Field进行取值

在这里插入图片描述

Method介绍(重点)

Java.lang.reflect.Method它描述的是类或接口中的方法。

如何获取一个Method对象

在这里插入图片描述

在这里插入图片描述

Method如何使用?

在这里插入图片描述

Method的invoke使用时注意事项?

  1. 如果方法是static,我们怎样调用?

如果方法是静态的,在通过invoke调用时不需要传递对象

// 调用static方法
@Test
public void test4() throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Class clazz = User.class;

	// 得到sum方法
	Method method = clazz.getMethod("sum"); // 注意sum是一个静态方法

	method.invoke(null);
}
  1. 如果方法的参数是一个数组类型,怎样处理?

// 调用参数是数组类型的方法
@Test
public void test5() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class clazz = User.class;

	// 得到sum方法
	Method method = clazz.getMethod("sum",Integer[].class); 
	
	//执行sum方法
	Integer[] args={1,2,3,4};
	//解决方案一:将args直接强制转换成Object在传递		
	//method.invoke(null, ((Object)args));		
	//解决方案二:在args这个数组外层在包装一层数组
	Object[] objs={args};
	method.invoke(null, objs);
	
}

反射案例

并提供get/set方法

public class Person {

	private String username;
	private String sex;
	private int age;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	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 "Person [username=" + username + ", sex=" + sex + ", age=" + age + "]";
	}

使用java中的反射技术将类中的属性与map中的key相同名称的,使用反射技术将key对应的value值赋值给属性.

采用两种方式完成操作

直接操作属性 Field来完成操作

// 通过属性来完成操作
	@Test
	public void test1() throws Exception {

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("username", "tom");
		map.put("age", 20);
		map.put("sex", "男");
		map.put("address", "北京");

		// 1.得到Person类的Class
		Class clazz = Class.forName("com.it.reflect.Person");
		Object obj = clazz.newInstance();
		// 2.得到Person类的所有属性
		Field[] fds = clazz.getDeclaredFields();
		// 3.得到map中所有的key
		Set<String> keys = map.keySet();
		for (Field f : fds) {
			String field_name = (f.getName()); // 得到属性名称

			if (keys.contains(field_name)) { // map的key中包含了Person类的属性
				// 4.将key对应的value赋值给属性
				f.setAccessible(true);
				f.set(obj, map.get(field_name));
			}
		}

		System.out.println(obj);
	}

通过属性对应的setXxx方法来完成操作

// 通过属性对应setXxx方法来完成操作
	@Test
	public void test2() throws Exception{
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("username", "tom");
		map.put("age", 20);
		map.put("sex", "男");
		map.put("address", "北京");

		// 1.得到Person类的Class
		Class clazz = Class.forName("com.it.reflect.Person");
		Object obj = clazz.newInstance();
		
		//2.得到Person类中的方法
		Method[] methods = clazz.getDeclaredMethods();
		
		//3.遍历map
		for(String key:map.keySet()){
			//将所有的key前面添加上set,与方法的名称不区分大小写来对比。
			String methodName="set"+key; //操作的方法
			for(Method method:methods){
				String mname=method.getName();
				if(methodName.equalsIgnoreCase(mname)){
					method.invoke(obj, map.get(key));
				}
			}
		}
		
		System.out.println(obj);
		
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值