反射

一、反射技术

反射:从字节码文件获取信息并进行操作

二、反射的原理

对类进行编译会生成字节码文件
第一次主动使用实体类时,会把字节码文件加载到方法区里,并且生成字节码文件对应的对象,该对象是Class类型。
Class类:不论是哪个字节码文件,加载到方法区里都会生成的一个对应的对象,这些对象都有一些共同的特征或行为,例如类定义,类名,构造,方法,属性等特征。根据这些共同特征,向上抽取了一个类,叫Class类。Class类提供了一些功能,对于字节码文件对应的对象,可以去调用Class类的功能去获得他们对应的字节码文件中的所有数据信息。

三、获取Class的几种方式

package com.gaj.day05;

public class Student {
	private int no;
	public String name;
	
	public Student(){
		System.out.println("无参构造");
	}
	public Student(int no, String name) {
		this.no = no;
		this.name = name;
		System.out.println("带参构造:" + this.no + "," + this.name);
	}
	public void method(){
		System.out.println("无参方法");
	}
	public String function(String str, int num){
		return "代参方法:" + str + ":" + num;
	}
	
}

package com.gaj.day05;

/**
 * 对字节码文件进行操作
 * 3种方式获取Class
 * @author Jan
 *
 */
public class Demo1 {

	public static void main(String[] args) {
		// 方式一:明确知道返回类型
		// 代码中需要直接用上该类
		Class<Student> c1 = Student.class;
		// 方式二:创建一个对象并getClass
		// 返回类型是Student以及Stundent的子类型
		// 代码中需要直接用上该类并且创建了对象
		Class<? extends Student> c2 = new Student().getClass();
		// 方式三:字符串:全限定名 会抛异常
		// 返回类型不确定 
		// 推荐,作为字符串的形式加载,更灵活
		try {
			Class<?> c3 = Class.forName("com.gaj.day05.Student");
			System.out.println(c3);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		System.out.println(c1);
		System.out.println(c2);
		
	}

}

三、反射的获取和操作

1、获取/操作属性

package com.gaj.day05;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
 * Field
 * 对属性的访问和操作
 * @author Jan
 *
 */
public class Demo2 {

	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
		Class<?> c = Class.forName("com.gaj.day05.Student");
		// 获取所有public属性
		Field [] fs = c.getFields();
		// 获取所有访问权限的属性
		fs = c.getDeclaredFields();
		for (Field field : fs) {
			// 获得属性名称
			System.out.println(field.getName());
			// 获得类型
			System.out.println(field.getType());
			// 获得访问权限 
			// field.getModifiers()是数字,需要通过Modifier的tostring方法进行转换
			System.out.println(Modifier.toString(field.getModifiers()));
		}
		// 获得单个属性
		Field f = c.getDeclaredField("name");
		// 创建一个对象
		Object obj = c.newInstance();
		// 给属性赋值
		f.set(obj, "Tom");
		// 获取这个属性
		System.out.println(f.get(obj));
		
		// 设置private属性 会抛出异常
		f = c.getDeclaredField("no");
		// 赋予修改权限
		f.setAccessible(true);
		f.set(obj, 1);
		System.out.println(f.get(obj));
	}

}

2、获取/操作方法

package com.gaj.day05;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * Method
 * 对方法的访问和操作
 * @author Jan
 *
 */
public class Demo3 {

	public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException {
		Class<?> c = Class.forName("com.gaj.day05.Student");
		Method [] ms = c.getDeclaredMethods();
		for (Method method : ms) {
			// 获得名称
			System.out.println(method.getName());
			// 获得返回值类型
			System.out.println(method.getReturnType());
			// 获得参数类型 getParameterTypes返回一个数组
			System.out.println(Arrays.toString(method.getParameterTypes()));
		}
		// 单个方法
		Method m = c.getDeclaredMethod("method");
		// 创建对象
		Object obj = c.newInstance();
		// 调用方法
		m.invoke(obj);
		// 带参方法
		m = c.getDeclaredMethod("function", String.class, int.class);
		System.out.println(m.invoke(obj, "hello", 999));
	}

}

3、获取/操作构造

package com.gaj.day05;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

/**
 * Constructor
 * 对构造的访问和操作
 * @author Jan
 *
 */
public class Demo4 {

	public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException {
		Class<?> c = Class.forName("com.gaj.day05.Student");
		Constructor<?> [] crs = c.getDeclaredConstructors();
		for (Constructor<?> constructor : crs) {
			System.out.println(Arrays.toString(constructor.getParameters()));
		}
		// 获得无参构造
		Constructor<?> cr = c.getDeclaredConstructor();
		cr.newInstance();
		// 带参构造
		cr = c.getDeclaredConstructor(int.class, String.class);
		cr.newInstance(22, "Tom");
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值