Java反射

1、Java的类加载机制

(1)概念
Java中的类加载机制指虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换、解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型。
它将类的各个组成部分封装成了不同的对象。方便操作

(2)作用:
对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性

(3)java代码在计算机中经历的阶段
*源代码阶段(硬盘中):.java文件 被javac编译为.class文件
*Class类对象阶段(内存中):类加载器将.class文件加载进内存,生成class类对象
*运行时阶段:创建对象后进入Runtime状态

2、获取Class对象
同一个字节码文件在一次程序运行过程中,只会被加载一次。

(1)源代码阶段:
将字节码文件加载进内存,返回class对象:Class.forName(“全类名”);
(2)Class类对象阶段:
类名.class;
(3)运行时阶段:
对象.getClass;

    //1、源代码阶段
    Class cla1 = Class.forName("cn.sweetie.login.domain.Person2");//全包类名
    //2、Class类对象阶段
    Class cla2 = Person2.class;
    //3、运行时阶段
    Person2 person2 = new Person2();
    Class cla3 = person2.getClass();

3、通过class对象获取成员变量们Fields

(1)方法:
*获取public修饰的成员变量
Field[] getFields();
Field getField(String name);
*获取被任何修饰符修饰的成员变量
Field[] getDeclaredFields();
Field getDeclaredField(String name);

(2)对获取来的成员变量后,获取值和改变值
a.获取值 get(Object object)
b.改变值 set(Object object,Object value)

注意:1、不是public修饰的变量,要进行暴力反射,才能成功get、set值。
	 	暴力反射:成员变量对象名.setAccessible(true);

			Class cla2 = Person2.class;
			Field id = cla2.getDeclaredField("id");
	        Person2 person2 = new Person2();
	        id.setAccessible(true);
	        id.get(person2);

	2、如果是final修饰的成员变量,反射可以修改成功包装类型的变量值;基本类型和String类型修改不成功

	   *person2.java
		private final Integer id = 1;
	    private final int age = 18;
		public Integer getId() {
	        return id;
	    }
	
	    public int getAge() {
	        return age;
	    }
		
	   *test.java
		Class cla2 = Person2.class;
		Person2 person2 = new Person2();
		Field id = cla2.getDeclaredField("id"); //Integer
	    Field age = cla2.getDeclaredField("age"); //int
		id.setAccessible(true);
	    age.setAccessible(true);
		id.set(person2,2);
	    age.set(person2, 19);
		Integer id1 = person2.getId();
	    int age1 = person2.getAge();
		System.out.println(id.get(person2)); //2
	    System.out.println(person2.getId()); //2
	    System.out.println(age.get(person2)); //19
	    System.out.println(person2.getAge()); //18

4、通过class对象获取构造方法们Constructors

(1)方法:
*获取public修饰的构造方法
Constructor getConstructor(Class<?>… parameterTypes)
Constructor<?>[] getConstructors()
*获取被任何修饰符修饰的构造方法
Constructor getDeclaredConstructor(Class<?>… parameterTypes)
Constructor<?>[] getDeclaredConstructors()

(2)用获取来的构造器创建对象
构造器对象.newInstance()

注意:用反射获取非public修饰的构造器方法后,创建对象要进行暴力反射
	 构造器对象名.setAccessible(true);

(3)特殊:如果是public修饰的空参构造,直接使用class类对象.newInstance()来创建对象

5、通过 class对象获取成员方法们Methods

(1)方法:
*获取public修饰的成员方法
Method[] getMethods()
Method getMethod(String name, Class<?>… parameterTypes)
*获取被任何修饰符修饰的成员方法
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, Class<?>… parameterTypes)

(2)执行方法
Object invoke(Object obj, Object… args)

	 Class cla2 = Person2.class;
	 Person2 person2 = new Person2();
	 Method eat = cla2.getMethod("eat",String.class);
     eat.invoke(person2,"菠菜");

注意:用反射获取非public修饰的成员方法后,调用方法要进行暴力反射
	 成员方法对象名.setAccessible(true);

6、用 class对象获取全类名
String getName()

练习

题目:写一个“框架”,要求可以调用任意类的任意空参方法。

思路:在配置文件里写类名和方法名,用反射将是该类名的类加载进入内存,创建对象,并调用是该方法名的方法。

解答:
(1)在src根目录下创建pro.properties配置文件。里边有类名信息和方法名信息。使用者可以仅通过修改配置文件来调用任意类的任意方法

		className = cn.sweetie.reflect.domain.Student  //全类名
		methodName = sleep

(2)写两个JavaBean样例,里边有无参的成员方法

(2)使用反射
	
		1、加载配置文件进入内存
			InputStream rs = ReflectDemo.class.getClassLoader().getResourceAsStream("pro.properties");
		2、使用properties集合(Map-》HashTable-》Properties)load 输入流对象,将配置文件中键值对存储到集合中来。
			Properties properties = new Properties();
			properties.load(rs);
		3、拿到类名和方法名
			String className = properties.getProperty("className");
       		String methodName = properties.getProperty("methodName");
		4、加载该类进入内存
			Class<?> cla = Class.forName(className);
		5、使用 类对象.方法名 创建对象(JavaBean中有空参构造方法的话)
			Object o = cla.newInstance();
		6、通过类对象找到该方法
			Method method = cla.getMethod(methodName);
		7、调用方法,传入对象参数
			method.invoke(o);	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值