【基础提升】反射总结

一、反射概述

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

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

反射需要用到的成员及方法

  1. Class类
  2. Constructor 构造
  3. Method 方法
  4. Filed 字段
  5. instance 实例
  6. invoke 执行

二、反射的准备

提供JavaBean,用于之后反射操作 JavaBean规范

 1.提供私有字段,例如:private String id;

 2.必须提供getter或setter方法 (可以使用快捷键生产,alt+shift+s)

 3.提供无参构造方法

 4.必须实现序列化接口

示例代码:

import java.util.Arrays;

public class Bean implements java.io.Serializable {
	
	private String id;
	private String className;
	public String description;
	
	//无参构造方法
	public Bean() {
		System.out.println("bean 无参构造");
	}
	
	
	public Bean(String id) {
		super();
		System.out.println("bean 1参数构造");
		this.id = id;
	}
	

	private Bean(String id, String className) {
		super();
		this.id = id;
		this.className = className;
	}

	//方法
	public void setId(String id){
		this.id = id;
	}
	public String getId(){
		return id;
	}
	
	public void setClassName(String className){
		this.className = className;
	}
	public String getClassName(){
		return this.className;
	}
	//私有方法
	private void show(int num){
		System.out.println("私有方法 :" + num);
	}
	
	//main方法
	public static void main(String[] args) {
		// * 将指定的数组转换成字符串
		System.out.println(Arrays.toString(args));
	}
	

	@Override
	public String toString() {
		return "Bean [id=" + id + ", className=" + className+ ", desc=" + description + "]";
	}
}

三、反射class的获取

三种获取方式及应用场景:

1 通过类型获得

 语法:类名.class

 应用场景:确定类型 等

Class clazz1 = Bean.class;

2 通过实例对象获得

 语法:变量.getClass()

 应用场景:在方法内部通过参数获得类型 等

Bean bean = new Bean();

Class clazz2 = bean.getClass();

3 通过字符串获得

 语法:Class.forName("全限定类名")

 应用场景:通过配置获得字符串 等

Class clazz3 = Class.forName("com.itheima_00_Bean.Bean");

示例代码:

public class ClassDemo_01 {
	@Test
	public void demo01() throws Exception{
		// 通过字符串获得
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		System.out.println(clazz);
	}
	
	@Test
	public void demo02() throws Exception{
		// 通过Java类型获得
		Class clazz = Bean.class;
		System.out.println(clazz);
	}
	
	@Test
	public void demo03() throws Exception{
		// 通过实例对象获得
		Bean bean = new Bean();
		Class clazz = bean.getClass();
		System.out.println(clazz);
	}
}

 四、反射操作类中成员

4.1 反射操作构造方法

1、通过获取public的构造创建对象

步骤:

1.获得Class对象

2获得构造

3.通过构造对象获得实例化对象

示例代码:

import java.lang.reflect.Constructor;

import org.junit.Test;

import com.mukvin.Bean;

public class ConstructorDemo_01 {
	
	@Test
	public void demo01(){
		//触发 无参构造方法
		Bean bean = new Bean();		
	}
	
	@Test
	public void demo02() throws Exception{
		/* 通过 无参构造方法 获得实例对象
		 * 1.获得Class对象
		 * 2.通过clazz获得无参构造
		 * 3.通过构造对象获得实例化对象
		 */
		//1 获得Class
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		
		//2 获得构造对象 , 相当于:Bean()
		// * getConstructor() 获得指定形参列表的构造方法
		Constructor cons = clazz.getConstructor();
		
		//3 获得实例 , 相当于:new Bean()
		// * newInstance() 创建实例对象,需要设置实际参数
		Object obj = cons.newInstance();		
	}

	@Test
	public void demo03() throws Exception{
		/* 通过 有参构造 获得实例
		 * Bean bean = new Bean("b001");
		 */
		// 1 获得Class对象
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		
		// 2 获得构造,必须指定形参
		Constructor cons = clazz.getConstructor(String.class);
		
		// 3 获得实例对象,必须设置实际参数
		Object obj = cons.newInstance("b002");
		
		System.out.println(obj);
	}	

	@Test
	public void demo04() throws Exception{
		
		// 无参构造 快速获得实例方式
		//1 获得Class
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		//2 通过clazz直接创建对象
		Object obj = clazz.newInstance();
		
		
	}
}

2 通过获取private的构造方法创建对象

步骤:

1 获得Class对象

2.获得 指定形参  私有构造

3.通知jvm,运行实例化私有构造

4.创建实例,并设置实际参数

示例代码:

        @Test
	public void demo02() throws Exception{
		
		// 通过 私有构造方法 创建实例对象
		
		//1 获得Class对象 
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		//2 获得 指定形参  私有构造 
		// * clazz.getConstructor(...) 获得指定对象的指定的public构造方法
		// * clazz.getDeclaredConstructor( ... ) 获得指定对象的指定的任意构造方法
		Constructor cons = clazz.getDeclaredConstructor(String.class ,String.class);
		
		//3 通知jvm,运行实例化私有构造(默认不允许)
		cons.setAccessible(true);
		
		//4 创建实例,并设置实际参数
		Object obj = cons.newInstance("b001","名称");
		
		System.out.println(obj);
	}

 4.2 反射操作成员方法

1、通过反射运行public方法

步骤:

1 获得实例

2 通过 setId 方法,设置数据

    2.1获得方法 ,需要明确形参列表,setId

    2.2 执行方法 ,bean.setId(...)

3.确定实例对象,并执行确定方法,具体实际参数

示例代码:

public class MethodDemo_01 {
	
	@Test
	public void demo01(){
		Bean bean = new Bean();
		bean.setId("b001");
		String id = bean.getId();
		System.out.println(id);
	}
	
	@Test
	public void demo02() throws Exception{
		//1 获得实例
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		Object obj = clazz.newInstance();
		
		//2 通过 setId 方法,设置数据
		//2.1 获得方法 ,需要明确形参列表,setId
		Method method = clazz.getMethod("setId", String.class);
		//2.2 执行方法 ,bean.setId(...)
		// * 确定实例对象,并执行确定方法,具体实际参数
		method.invoke(obj, "b002");
		
		System.out.println(obj);
	}
	
	@Test
	public void demo03() throws Exception{
		//1 获得实例
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		Object obj = clazz.newInstance();
		
		//2 通过 setId 方法,设置数据
		//2.1 获得方法 ,需要明确形参列表,setId
		Method method = clazz.getMethod("setId", String.class);
		//2.2 执行方法 ,bean.setId(...)
		// * 确定实例对象,并执行确定方法,具体实际参数
		method.invoke(obj, "b002");
		
		//3 通过  getId 方法,获得数据
		Method getMethod = clazz.getMethod("getId");
		String str = (String) getMethod.invoke(obj);
		
		System.out.println(str);
	}
}

2、通过反射运行public方法流

步骤:

1 获得实例

2 执行方法

   2.1 获得方法

   2.2 强制设置运行访问私有访问(暴力)

2.3 执行方法

public class MethodDemo_02 {
	@Test
	public void demo01() throws Exception{
		
		// 执行 bean 私有方法
		
		//1 获得实例
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		Object obj = clazz.newInstance();
		
		//2 执行方法
		// 2.1 获得方法 
		// * clazz.getMethod(name,... ) 只能获得public类型方法
		// * clazz.getDeclaredMethod(name,... ) 获得已声明的方法
		Method method = clazz.getDeclaredMethod("show", int.class);
		
		// 2.2 强制设置运行访问私有访问(暴力)
		method.setAccessible(true);
		
		// 2.3 执行方法
		Object r = method.invoke(obj, 18);
		
		System.out.println(r);
		
	}
	
	
	@Test
	public void demo02() throws Exception{
		// 执行 静态方法 main
		//1 获得实例,不需要
		//2 执行方法,必须需要Class对象
		
		//1 获得Class对象
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		
		//2获得main方法
		Method method = clazz.getMethod("main", String[].class);
		
		//3 执行main方法
		// * 参数1:为实例对象(变量名),static方法不需要
		// * 参数2:main方法执行的实际参数
		// ** 可变参数在执行时,JVM内部将传递实参数组打散,变成多个参数。
		// **** method.invoke(null, args);
		// 等效	method.invoke(null, "abc","123","xxx");
		String[] args = {"abc","123","xxx"};
		//method.invoke(null, args); 		//错误写法
		// * 数组参数需要特殊处理
		// ** 方式1:将 String[]转换成Object,可变参数将不处理数组
		method.invoke(null, (Object)args);
		// ** 方法2:将提供二维数组,args将作为二维数组的第一个数。
		method.invoke(null, new Object[] {args});
		
	}
}

4.3  反射操作成员属性

1、反射public属性

步骤:

1 获得实例对象

2 给字段赋值

3 获得字段值

示例代码:

public class FieldDemo_01 {
	@Test
	public void demo01() throws Exception{
		
		//1 获得实例对象
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		Object obj = clazz.newInstance();
		
		
		//2 给字段赋值
		Field field = clazz.getField("description");
		field.set(obj, "描述");
		
		//3 获得字段值
		String str = (String) field.get(obj);
		
		System.out.println(str);
		
	}
}

2、反射private属性

步骤:

1 获得实例

2 获得声明的字段(私有)

3 设置运行访问私有(暴力)

4 设置数据

5 获得数据

示例代码:

        @Test
	public void demo02() throws Exception{
		
		//私有字段
		
		//1 获得实例
		Class clazz = Class.forName("com.itheima_01_bean.Bean");
		Object obj = clazz.newInstance();
		
		//2 获得声明的字段(私有)
		// * clazz.getField(name)   获得公共字段
		// * clazz.getDeclaredField(name) 获得声明字段(含私有)
		Field field = clazz.getDeclaredField("className");
		
		//3 设置运行访问私有(暴力)
		field.setAccessible(true);
		
		//4 设置数据
		field.set(obj, "名称");
		
		//5 获得数据
		String className = (String) field.get(obj);
		
		System.out.println(className);
	}

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值