反射入门详解

一、反射的机制
二、jvm中字节码文件的生命周期
三、java中九大内置class实例及对应的数组实例
四、Class对象获取方式及其使用
五、反射的应用

一、反射的机制
java的反射是指程序在运行的过程中,可以动态地获取到任意一个对象的Class实例,并且可以通过这个实例获得该对象的成员变量、构造函数、方法,从而实现动态地创建对象,执行该对象的方法,因为反射可以暴力获取到类中的私有变量或方法,破坏了Java的封装特性,所以存在一定风险性。

二、jvm中字节码文件的生命周期
在jvm中class字节码文件的生命周期分为:加载、连接、初始化、使用、卸载的5个阶段
1、加载(loading)是指通过jvm当中的ClassLoader将class文件加载到内存的常量池当中,并将其中的静态变量和常量放入方法区当中(jdk1.8之后在元空间,使用的是本地内存,而不是jvm当中的内存)

2、连接(linking):分为校验、准备、解析三个阶段
2.1校验(verification):校验字节码文件当中的编码等是否正确
2.2准备(preparation):将静态变量和常量默认初始化
2.3解析(resolution):将符号引用转变为直接引用(为常量池当中的符号引用即类中的方法等开辟空间)

3、初始化(initialization):为静态变量和常量真正初始化

4、使用(using):使用该对象

5、卸载(unloading):gc回收掉

三、java中九大内置class实例及对应的数组实例
java中九大内置class实例包括8大基本数据类型以及void的class对象,因为基本数据类型没有类的具体名称,也没有getClass方法,所以只能通过class属性(int.class)来获取对应的类对象
注意:
1、基本数据类型及其对应的包装类的类对象不是同一个class对象,即Integer.class!=int.class,但是在每个基本类型的包装类中都有个TYPE常量,这个常量就是其对应的基本类型的类对象,即Integer.TYPE==int.class。
2、数组类型的类对象是看他们的维数和类型,就是说一维的String类型数组共享一个一维的String类对象
String[] str = {1,2,3};
Striing[] str1={0};
String str3=“asd”;
str.getClass()!=str3.getClass();
str.getClass()==str1.getClass();

四、Class对象获取方式及其使用
1、class对象的获取方式有三种:
1.1源码阶段:Class.forName(包名+类名);
1.2字节码文件阶段:类名.class;
1.3运行时阶段:对象.getClass();

2、class对象的使用
2.1获取成员变量
getField(String name)
getFields() 获取public修饰的全部成员变量
getDeclaredFields() 获取全部的成员变量
getDeclaredField(String name)
获取Field的作用:
(1)get:获取该对象的成员变量的值
(2)set:设置该对象成员变量的值
2.2获取构造方法
getDeclaredConstructors()
getDeclaredConstructor(Class<?>… parameterTypes)
getConstructor(Class<?>… parameterTypes)
getConstructors()
获取构造器的作用
(1)动态创建对象:newInstance();
2.3获取方法
getDeclaredMethods()
getDeclaredMethod(String name, Class<?>… parameterTypes)
getMethods()
getMethod(String name, Class<?>… parameterTypes)
获取方法的作用
(1)运行方法:invoke();
2.4获取包
getPackage()
2.5获取注解
getAnnotation(Class annotationClass)
getAnnotations()

五、反射的应用
需求:构造一个应用,可以动态的加载指定类,运行指定的方法
步骤:
1、创建properties文件存放指定的类以及指定要运行的方法

classPath=com.djn.Refection.Person
methon=eat
name=张三
thing=冰激凌

2、创建类Person,通过反射获取该类对象并运行指定方法

package com.djn.Refection;

public class Person {
	
	@SuppressWarnings("unused")
	private void eat(String name, String thing) {
		System.out.println(name + "吃" + thing);
	}

}

package com.djn.Refection;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Properties;

/*
 * 需求:构造一个应用,可以动态的加载指定类,运行指定的方法
步骤:
1、创建properties文件存放指定的类以及指定要运行的方法
2、创建类,通过反射获取该类对象并运行指定方法
 */
public class RefectionDemo {

	public static void main(String[] args) throws Exception {
		//1、读取Refection.properties文件内容
		Properties  properties = new Properties();
		Class<?> clazz = Class.forName("com.djn.Refection.RefectionDemo");
		InputStream inputStream = clazz.getClassLoader().getResourceAsStream("Refection.properties");
		InputStreamReader inputStreamReader = 
				new InputStreamReader(inputStream, "utf-8");//需要读中文,因此需要指定编码
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		properties.load(bufferedReader);
		String classPath = properties.getProperty("classPath");
		String methon = properties.getProperty("methon");
		String name = properties.getProperty("name");
		String thing = properties.getProperty("thing");
		//2、获取指定类的类对象
		Class<?> clazz1 = Class.forName(classPath);
		//3、获取指定方法并运行
		Method method1 = clazz1.getDeclaredMethod(methon, String.class, String.class);//两个参数,第一个是方法名,第二个是方法的参数类型类对象(可以多个)
		method1.setAccessible(true);//暴力反射,可以运行私有方法
		method1.invoke(clazz1.newInstance(), name, thing);//两个参数,第一个是对应方法对应类的实例对象,第二个是方法的实际传值(可以多个)
	}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值