java 反射 - 从入门到放弃

发布于 更新于
本文目录
  1. 1、什么是反射
  2. 2、反射的应用场景
  3. 3、反射优缺点
  4. 4、类加载过程
  5. 5、反射常用 API

技术文章

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

1、什么是反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
举个例子:
创建java对象时,一般是要知道类名,比如创建Student对象。
Student s = new Student();
但是有些时候,当前时间不知道类名,我又想能创建这个类的对象,这时候就不需要用到反射。
只需要拿到字节码对象,我们就能通过反射获取对象、调用方法、访问变量。
从而脱离必须在java文件中把类名写死,java赋予的这种能力,广泛运用在各大流行框架中。


2、反射的应用场景

1. 封装对象(比如把excel中一行数据封装到一个自定义对象中)
2. 工具类(比如testng、fastjson)
3. Spring框架


3、反射优缺点

优点:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,避免将程序写死到代码里。
缺点:通过反射创建对象比直接写代码创建对象会慢一些,因为使用反射时进行一系列的安全性校验,加载字节码也会比较慢。


4、类加载过程

上面介绍了反射的优缺点,那为什么反射会比较慢呢?这就要说到类加载过程。
类加载机制:
加载--->链接(验证、准备、解析)--->初始化--->使用--->卸载
1. 加载:字节码.class文件加载到内存中
2. 链接:
	1、验证字节码是否被篡改
	2、准备分配对应的空间
	3、解析字节码对应类的字段、父类、接口等
3. 初始化:相当于 new Student(); 创建类的对象
4. 使用:对象调用对象方法、字段等
5. 卸载:对象被回收


5、反射常用 API

1、获取字节码对象

//Class.forName()Class clazz1 = Class.forName("com.lemon.Lemon");//类名.classClass clazz2 = Lemon.class;//getClass()Lemon l = new Lemon();Class clazz3 = l.getClass();//通过三种方式获取的字节码对象都是相同,使用两两相等的方式比较。System.out.println(clazz1 == clazz2);System.out.println(clazz1 == clazz3);


2、创建对象

//有两种方式可以创建对象,一用字节码调用newInstance(),二是先获取Constructor对象,在调用newInstance()Object o1 = clazz1.newInstance();//获取Constructor//获取指定构造方法Constructor constructor = clazz1.getConstructor(构造方法参数类型);//获取所有构造方法Constructor[] constructors = clazz1.getConstructors();//执行构造方法Object o2 = constructor.newInstance(参数);


3、获取属性和方法

//获取字段Field field = clazz1.getField(字段名称);Field[] fields = clazz1.getFields();//设置字段field.set(对象,字段值);//获取字段Object value = filed.get(对象);//获取方法Method method = clazz1.getMethod(方法名,方法参数类型);Method[] methods = clazz1.getMethods();//执行方法Object result = method.invoke(对象,方法参数):


4、暴力反射

//被private修饰的方法和字段只能在本类访问,但是通过反射可以强行获取,这在一定程度上破坏了封装性//上面获取构造方法、字段、方法还有一组加了Declared修饰的方法,用它就能来访问所有内容(public、protected、默认、private)//ConstructorgetDeclaredConstructors();getDeclaredConstructor(构造方法参数类型);//FieldgetDeclaredFields();getDeclaredField(字段名称);//MethodgetDeclaredMethods();getDeclaredMethod(方法名,方法参数类型);//当你获取到非公有内容还不能直接使用,还需要调用setAccessible(true)设置访问权限constructor.setAccessible(true);field.setAccessible(true);method.setAccessible(true);//好了,这样就能用尽情的使用java类中所有成员了,哦也~




继续阅读