xml基本使用-------------反射详解

本文介绍了Java反射机制,包括类的初始化、反射概述、Class获得方式、构造方法与实例、方法与执行、字段与数据操作等内容,还涉及暴力反射。此外,讲解了BeanUtils工具类,包括其功能和常用API,并给出了综合案例,如读取配置文件设置对象属性等。

第2章 反射

能够说出反射的概念

能够说出获取一个类的class文件对象的三个方式

能够实现反射构造方法

能够实现反射方法

能够使用BeanUtils工具类方法setProperty

能够使用BeanUtils工具类方法getProperty

能够完成BeanUtils工具类的综合案例

1.1 类的初始化

  1. 创建类的实例

  2. 类的静态变量,或者为静态变量赋值

  3. 类的静态方法

  4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

  5. 初始化某个类的子类

  6. 直接使用java.exe命令来运行某个主类

到目前为止我们已经知道把class文件加载到内存做了哪些事情了,那么,如果我们仅仅站在这些class文件的角度,我们如何来使用这些class文件中的内容呢?那就是我们反射将要学习的内容了。

1.2反射概述

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

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖这个类,使用的就是Class类中的方法,所以先要获取到每一个字节码文件所对应的Class类型对象。

类的加载器把要运行的类装进内存。
类的加载器有三个:
(1)引导类加载器:由C语言编写(加载使用的核心类库)
(2)扩展类加载器:Java语言编写(加载JDK的扩展类库)
(3)应用类加载器:Java语言编写(加载我们写的类)
Java.lang.ClassLoader表示类的加载器的对象
一个类只能被加载一次,不能被加载两次
对象都是由类产生的

[外链图片转存失败(img-Sn9rDcZB-1562192873796)(pics/搜狗截图20190520112521.png)]

1.3 准备数据

自定义一个类

1.4知识储备

需要掌握6个单词

Class类

Constructor 构造

Method 方法

Field 字段

instance 实例

invoke 执行

1.5 Class获得方式

//1 通过类型获得
// 语法:类名.class
// 应用场景:确定类型等
Classclazz1 = Bean.class;


//2 通过实例对象获得
// 语法:变量.getClass()
// 应用场景:在方法内部通过参数获得类型等
Bean bean = newBean();
Classclazz2 = bean.getClass();

//3 通过字符串获得
// 语法:Class.forName("全限定类名")
// 应用场景:通过配置获得字符串等
Classclazz3 = Class.forName("com.baidu.Bean");

1.6 构造方法与实例

添加有参无参构造方法

1.6.1 无参构造

无参构造,并获得实例

public void test DefaultCons() throws Exception{
	//无参构造 , 并实例化
	
	//1获得Class
	Class beanClass = Bean.class;
	
	//2获得构造 -- 没有形参
	Constructorconstructor = beanClass.getConstructor();
	
	//3 实例对象,没有实参
	Object bean = constructor.newInstance();
	System.out.println(bean);
	
	/* 结果:
	 * 无参构造
	 * com.baidu.Bean@8c5488
	 */
}

1.6.3 有参构造

有参构造,并获得实例

publicvoidtestParamCons() throws Exception{
	//有参构造 , 并实例化
	
	//1获得Class
	ClassbeanClass = Bean.class;
	
	//2获得构造 -- 两个字符串形参 -- Bean(String id, String className)
	Constructorconstructor = beanClass.getConstructor(String.class,String.class);
	
	//3 实例对象,两个字符串实参
	Object bean = constructor.newInstance("ArrayListId","java.util.ArrayList");
	System.out.println(bean);
	
	/* 结果:
	 * 有参构造:ArrayListId,java.util.ArrayList
	 * com.baidu.Bean@101acff
	 */
}

1.6.4 无参构造,简化版获得实例

无参构造,简化版获得实例

publicvoidtestDefaultSimple() throws Exception{
	//无参构造 , 简化版
	
	//1获得Class
	ClassbeanClass = Bean.class;
	
	//2 直接获得实例对象,两个字符串实参
	Object bean = beanClass.newInstance();
	System.out.println(bean);
	
	/* 结果:
	 * 无参构造
	 * com.baidu.Bean@101acff
	 */
}

1.6.5 扩展:私有构造(暴力反射)

修改Bean添加私有构造

getConstructor() 使用该方法将无法获得私有方法,程序运行抛异常

没有使用setAccessible(true),将抛异常

publicvoidtestPrivateCons() throws Exception{
	//私有构造
	
	//1获得Class
	Class beanClass = Bean.class;
	
	//2获得构造 -- 两个字符串形参 -- Bean(String id, String className)
	// * getConstructor() 将抛异常java.lang.NoSuchMethodException
	// * getDeclaredConstructor可以获得私有构造
	Constructor constructor = beanClass.getDeclaredConstructor(String.class);
	
	//暴力访问
	constructor.setAccessible(true);
	
	//3 实例对象,两个字符串实参
	Object bean = constructor.newInstance("userId");
	System.out.println(bean);
	
	/* 结果:
	 * 有参构造:userId
	 * com.baidu.Bean@8c5488
	 */
}

1.7方法与执行

1.7.1 添加set、get方法

//Bean类提供getter和setter方法
public String getId() {
	System.out.println("getId方法执行");
	return id;
}
public void setId(String id) {
	System.out.println("setId方法执行:" + id);
	this.id = id;
}

1.7.2 public方法

publicvoidtestMethod() throws Exception{
	
	//1 获得Class
	Class clazz = Class.forName("com.baidu.Bean");
	
	//2 获得实例 ,相当于  Object obj = new Bean();
	Object obj = clazz.newInstance(); 
	
	
	//3 操作setId方法
	//3.1 获得的方法,一个形参
	// * 格式:getMethod(方法名,参数列表)
	Method setMethod = clazz.getMethod("setId", String.class);
	//3.2 执行方法,一个实参
	Object setReturnObj = setMethod.invoke(obj, "我是参数");
	
	System.out.println("set方法返回值:" + setReturnObj);
	
	/* 运行结果:
	 * 	无参构造
	 * 	setId方法执行:我是参数
	 * 	set方法返回值:null
	 */
	
	System.out.println("---------------");
	
	//4 操作getId方法 (巩固)
	// 3.1 获得方法,没有形参
	Method getMethod = clazz.getMethod("getId");
	// 3.2 执行方法,没有实参
	Object getReturnObj = getMethod.invoke(obj);
	
	System.out.println("get方法返回值:" + getReturnObj);
	
	/* 运行结果:
	 *	getId方法执行
	 *	get方法返回值:我是参数
	 */
}

1.7.3 扩展:私有方法(暴力反射)

//私有方法
private String show(){
	System.out.println("私有方法执行");
	return"Bean["+id+", "+ className +"]";
}

getMethod() 使用该方法将无法获得私有方法,程序运行抛异常

没有使用setAccessible(true),将抛异常

publicvoidtestPrivateMethod() throws Exception{
	//1 获得Class
	Class clazz = Class.forName("com.baidu.Bean");
	
	//2获得构造 -- 两个字符串形参 -- Bean(String id, String className)
	Constructor constructor = clazz.getConstructor(String.class,String.class);
	
	//3 实例对象,两个字符串实参
	Object bean = constructor.newInstance("ArrayListId","java.util.ArrayList");
	
	//3获得方法 -- 私有方法 -- private String show()
	// * getMethod(方法名,形成列表) 将抛异常java.lang.NoSuchMethodException
	// * getDeclaredMethod(方法名,形成列表) 可以获得私有构造
	Method showMethod = clazz.getDeclaredMethod("show");
	
	//暴力访问
	showMethod.setAccessible(true);
	
	// 4 执行方法,没有实参
	Object getReturnObj = showMethod.invoke(bean);
	System.out.println("show方法返回值:" + getReturnObj);
	
	/* 运行结果:
	 *	有参构造:ArrayListId,java.util.ArrayList
	 *	私有方法执行
	 *	show方法返回值:Bean[ArrayListId, java.util.ArrayList]
	 */
}

1.8 字段(成员变量)与数据操作(了解)

1.8.1 添加public字段

publicclass Bean {
	private String id;
	private String className;
	public String description;

1.8.2 public字段的操作

publicvoidtestField() throws Exception{
	/* 获得实例,为public字段赋值、获取值
	 * public String description;
	 */
	
	//1 获得Class
	Class clazz = Class.forName("com.baidu.Bean");
	
	//2 获得实例 ,相当于  Object obj = new Bean(); 但是必须是无参构造
	Object bean= clazz.newInstance(); 
	
	//3 操作字段,进行赋值,public String description;
	//3.1 获得的字段,一个形参
	// * 格式:getField(字段名)
	Field descriptionField = clazz.getField("description");
	//3.2 为对象的字段赋值
	descriptionField.set(bean, "Bean的描述");
	
	//3.3 获取对象的字段值
	Object fieldReturnObj = descriptionField.get(bean);
	System.out.println("description字段返回值:"+fieldReturnObj);
}

1.9 综合案例

  • 提供一个User对象,并提供getter和setter方法,并复写toString()
public class TbUser {
	
	private String id;
	private String username;
	private String pwd;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	//....省略
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", pwd=" + pwd + "]";
	}
  • 读取properties文件,将文件内容设置到User中

    /*
    	 * 读取配置文件(IO+集合),键值对存储到集合中
    	 * 键获取集合中的所有值
    	 * 反射,创建出User类的对象,调用方法setXX,数据存储
    	 */
    	public void test()throws Exception{
    		Properties pro = new Properties();
    		FileInputStream fis = new FileInputStream("data.properties");
    		pro.load(fis);
    		fis.close();
    		Class clazz = Class.forName("com.baidu.domain.User");
    		Object obj = clazz.newInstance();
    		Set<String> keys = pro.stringPropertyNames();
    		for(String key : keys){
    			String methodName = "set"+key.substring(0,1).toUpperCase()+key.substring(1);
    			Method method = clazz.getMethod(methodName, String.class);
    			method.invoke(obj, pro.getProperty(key));
    		}
    		System.out.println(obj);
    	}
    

    配置文件data.properties
    uid=001
    username=jack
    password=123

#第3章 BeanUtils工具类

BeanUtils 是 Apache commons组件的成员之一,主要用于简化JavaBean封装数据的操作。它可以给JavaBean封装一个字符串数据,也可以将一个表单提交的所有数据封装到JavaBean中。

​ 使用第三方工具,需要导入jar包:

[外链图片转存失败(img-CDOTWKM1-1562192873797)(pics/搜狗截图20190520113602.png)]

BeanUtils工具常用工具类有两个:BeanUtils、ConvertUtils。BeanUtils用于封装数据,ConvertUtils用于处理类型转换,常用API如下

[外链图片转存失败(img-0oJ7d8d9-1562192873797)(pics/搜狗截图20190520113632.png)]

  • 提供JavaBean User ,并提供对应的构造方法
public class User {

	private String id;
	private String username;
	private String pwd;
	//省略setter和getter
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", pwd=" + pwd + "]";
	}
}
  • 功能1:设置属性

public void demo01() throws Exception{
  User user = new User();

  //设置属性
  BeanUtils.setProperty(user, "id", "u001");
  BeanUtils.setProperty(user, "username", "jack");
  BeanUtils.setProperty(user, "pwd", "1234");

  System.out.println(user);

  /* 结果:
   * 	User [id=u001, username=jack, pwd=1234]
   */
  }
 
  • 功能2:获得属性
@Test
public void demo02() throws Exception{
	User user = new User("u001","jack","1234");

	//设置属性
	String id = BeanUtils.getProperty(user, "id");
	String username = BeanUtils.getProperty(user, "username");
	
	System.out.println(id);
	System.out.println(username);
	
	/* 结果:
	 * 	u001
	 *  jack
	 */
}
  • 功能3:封装表单数据,populate方法
public static void main(String[] args) throws Exception{
		
		Class clazz = Class.forName("com.baidu.demo4.User");
		User instance = (User)clazz.newInstance();
		//设置值
//		BeanUtils.setProperty(instance, "id", 1001);
//		BeanUtils.setProperty(instance, "username", "haha");
//		BeanUtils.setProperty(instance, "pwd", "123");
		
		//获取值
//		System.out.println(BeanUtils.getProperty(instance, "id"));
//		System.out.println(BeanUtils.getProperty(instance, "username"));
//		System.out.println(BeanUtils.getProperty(instance, "pwd"));
		
		Map<String, Object> properties=new HashMap<>();
		properties.put("id", 1001);
		properties.put("username", "qinghua");
		properties.put("pwd", 1111);
		
		//批量设置属性
		BeanUtils.populate(instance, properties);
		
		
		System.out.println(BeanUtils.getProperty(instance, "id"));
		System.out.println(BeanUtils.getProperty(instance, "username"));
		System.out.println(BeanUtils.getProperty(instance, "pwd"));
		
//		System.out.println(instance);
		
		
	}

2.1 综合案例

读取XML中的配置文件信息,使用BeanUtils工具类创建JavaBean对象,将XML中的数据保存到JavaBean类的属性中

/**
	 * 读取xml中的内容
	 * 通过反射 设置到对象中
	 * 测试
	 * 
	 */
	public static void main(String[] args) throws Exception{
		
		Class clazz = Class.forName("com.baidu.demo5.User");
		User user1 = (User)clazz.newInstance();
		User user2 = (User)clazz.newInstance();
		User user3 = (User)clazz.newInstance();
		
		ArrayList<User> userList = new ArrayList<User>();
		userList.add(user1);
		userList.add(user2);
		userList.add(user3);
		
		
		//读取beans.xml中的内容
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read("beans.xml");
		Element rootElement = document.getRootElement();
		List<Element> elements = rootElement.elements();
		for(int i=0;i<elements.size();i++) {
			User user = userList.get(i);
			BeanUtils.setProperty(user, "id", elements.get(i).attributeValue("id"));
			BeanUtils.setProperty(user, "username", elements.get(i).attributeValue("name"));
			BeanUtils.setProperty(user, "pwd", elements.get(i).attributeValue("pwd"));
		}
		
		for(User u:userList) {
			System.out.println(u);
		}
		
		
		
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值