JAVA中的反射技术

之前的学习一直都没有文字记录,发现过一段时间之后某些知识点就会遗忘,所以今后所学习的知识点将记录下来,以便以后用来复习。

这次来说说JAVA中的反射技术,说起反射技术我对于它一直以来都是一种懵逼的状态,有一种非常排斥它的心理。在实际中JAVA的反射机制非常重要,我们使用的许多的开发框架都是基于反射实现的。如果不能很好的理解学习反射技术将会对今后的学习或技术提升将是一个非常大的阻碍。

什么是反射?
JAVA反射机制是在程序运行状态中,对于任意一个实体类,都能够知道该类的所有的属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信息以及动态调用对象方法的功能称之为JAVA语言的反射机制。(摘抄自百度百科)。看了百度百科的介绍之后在说说我个人对于反射的一个理解:这段话也就是在讲**我们的应用程序可以在程序运行期间获得JAVA对象,并且可以动态的取得JAVA对象的属性和方法,并且对属性或方法进行操作。**这就是反射机制。

下面我们使用代码来进行演示:

首先先创建一个实体类Dog类

package pojo;

/**
 * Dog类
 * @author Patton
 *
 */
public class Dog {
	/* 属性 **/
	private String name ; 
	private Integer age ; 
	private Character sex ;
	
	/* 无参构造**/
	public Dog() {
		super();
		// TODO Auto-generated constructor stub
	}
	/* 带参构造**/
	public Dog(String name, Integer age, Character sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	
	/* get和set方法**/
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Character getSex() {
		return sex;
	}
	public void setSex(Character sex) {
		this.sex = sex;
	}
	
	/* toString()方法**/
	@Override
	public String toString() {
		return "Dog [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	} 
	
	/* say()方法**/
	public void say(){
		System.out.println("汪汪汪");
	}
}

1.正常方式获得JAVA对象

package test;

import pojo.Dog;

public class Test01 {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dog dog = new Dog("雷管", 8, '公') ; 
		System.out.println(dog.toString());
		dog.say() ; 
		
	}
}

这段测试代码也就new了一个Dog对象,然后调用了个方法而已,这是之前我们使用JAVA对象的一种普通的方式。然后在看看第二种方式获得JAVA对象。

2.反射方式获得JAVA对象
在使用之前先大概介绍几个反射中常常使用的方法.
获取某个类的类实例
获取构造函数对象
获取构造函数对象
获取属性对象
获取属性对象获取函数对象获取函数对象

package test;

import java.lang.reflect.Field ;
import pojo.Dog;
public class Test01 {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			//1.获取类的类实例
			//注意:
			//类的类实例指的是Dog类的类实例 , 
			//该处的c代表的是Dog类
			//它不同于Dog的实例对象
			Class<?> c = Class.forName("pojo.Dog") ;
			//2. c.newInstance() 表示Dog类的类实例调用newInstance方法创建Dog类的实例对象
			//Dog dog2 = (Dog) c.newInstance() ; 
			/**
			getDeclaredFields()方法获取所有的属性对象,不管是共有的还是私有的都可以直接获取
			Field[] fs = c.getDeclaredFields() ;
			for (Field field : fs) {
				System.out.println(field.getName());
			}
			*/
			/**
			 *  getDeclaredField(String str)方法获取指定的属性对象,不管是共有的还是私有的都可以直接获取
			 *  Field f = c.getDeclaredField("name") ; 
				System.out.println(f.getName());
			 */
			/**
			 getField()方法获取指定的非私有的属性对象
			 Field f = c.getField("name") ; 
			 System.out.println(f.getName());
			 */
			/**
			 * getFields获取所有的非私有的属性对象
			 * Field[] f = c.getFields() ; 
				for (Field field : f) {
					System.out.println(field.getName());
				}
			 */
			/**
			 * 获取其他的对象(函数对象,构造函数对象),都可以使用类似的方法进行获取,不再一一演示
			 */
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

通过以上的代码,我们的虽然知道了反射怎么使用,但是还是不知道在实际应用当中我们怎么使用反射编码。接下来我们在通过一个例子看一下反射基本的实际应用。

前情提要:
我们现在需要使用最原始的JDBC查询数据库,数据库中需要很多的表也就表明我们有非常多的实体,在一般情况下我们查询某个表后返回resultSet对象需要解析到对应的实体,如果只有几张表还好,只用写几次解析就可以,但是与如果有非常多的表,我每次都需要写解析岂不是非常的浪费时间。它们的解析模式都是一样的,不同的地方只有承载数据的容器(实体类)不同。所以我们可以使用反射技术帮助我们同一进行解析。

package util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.sql.ResultSet;

import pojo.Dog;
import pojo.Person;

public class Dbutil {
	
	/**
	 * 解析Object[] objs并动态创建对象赋值后将对象返回。
	 * 
	 * 在之前写代码如果有多个实体,那么在解析数据时就要对应写多个解析,现在我们使用反射技术只用写一个解析方法
	 * 就可以解决。
	 * 
	 * 
	 * 
	 * 
	 * 
	 * 
	 * @param cla 某个类的Class实例
	 * @param objs
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public static <T> T parserResultSet(Class<T> cla , Object[] objs) throws InstantiationException, IllegalAccessException{
		
		//1. 根据类的类实例cla创建出类的对象t
		//t是为我们动态创建的,我们也不知道程序在运行时需要什么,我已我们使用反射技术解决
		T t = cla.newInstance() ; 
		//2.获取所有的属性
		Field[] fields = cla.getDeclaredFields() ; 
		int index = 0 ; 
		
		for (Field field : fields) {
			//设置属性为可直接赋值
			field.setAccessible(true) ; 
			//为属性赋值
			//t:表示谁调用此属性
			//objs[index]:表示值
			field.set(t, objs[index]) ;
			index++ ; 
		}
		return t ; 
	}
	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		
		Dog dog = Dbutil.parserResultSet(Dog.class ,new Object[]{1, "雷管" , "男" , 5}) ; 
		System.out.println("++++++++++++++++");
		System.out.println(dog.toString());
		
		Person per = Dbutil.parserResultSet(Person.class, new Object[]{1 , "张三" , "120斤" , "175cm" , 23 , "男" , "陕西西安"}) ; 
		System.out.println("++++++++++++++++");
		System.out.println(per.toString());
	}
}	

好了这篇文章就先说说普通方式与使用反射技术方式的区别以及反射技术的基本用途,下篇文章在记录关于反射的其他知识点。
我会将练习代码上传到GitHub以供参考。https://github.com/zhangbojie/JAVA-reflection-mechanism.git

猜你喜欢

转载自blog.csdn.net/zbj17602900546/article/details/88630086