什么叫反射机制
1、反射机制允许程序员在执行期间借助于Reflection API 取得任何类的内部消息(比如成员变量,构造器,车成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到
2、加载完类之后,在堆中就会产生一个Class类型的对象(一个类只有一个Class对象),这个对象包含l类的完成结构信息,通过这个对象得到类的结构,这个class对象就像一面镜子,透过这个镜子看到类的结构,所有称之为反射
反射机制原理示意图
反射相关的主要类
反射的优点和缺点
反射调优
setAccessible 爆破执行 当不能访问私有的话 可以使用这个暴力执行
Class 类
一、基本介绍
Class 常用的api
package com.Class_demo;
import java.lang.reflect.Field;
/**
* @author ZhouHao
* @version 1.0
* 成为想成为的人
*/
//class 类常用的方法
public class class_method_01 {
public static void main(String[] args) throws Exception {
//1 . 获取到 Car 类 对应的 Class 对象
Class<?> cls = Class.forName("com.Class_demo.Car");
//2. 输出 cls 获取实例
System.out.println(cls);
System.out.println("运行类型是:"+cls.getClass());
//3. 得到包名
System.out.println(cls.getPackage().getName());
//4. 得到全类名
System.out.println(cls.getName());
//5. 通过 cls 创建对象实例
Object o = cls.newInstance();
//6. 通过反射获取属性 brand
Field brand = cls.getField("brand");
//7. 通过反射给属性赋值
brand.set(o, "奔驰");
System.out.println(brand.get(o));
//8 我希望大家可以得到所有的属性(字段)
Field[] fields = cls.getFields();
for (Field f:fields){
System.out.println(f.getName());
}
}
}
六种获取Class对象的方法
package com.Class_demo;
/**
* @author ZhouHao
* @version 1.0
* 成为想成为的人
*/
//获取class的六种方式
public class get_class {
public static void main(String[] args) throws Exception {
//1. Class.forName
Class<?> cls1 = Class.forName("com.Class_demo.Car");
//2. 类名.class , 应用场景: 用于参数传递
Class<Car> cls2 = Car.class;
//3. 对象.getClass(), 应用场景,有对象实例
Car car = new Car();
Class<? extends Car> cls3 = car.getClass();
//4. 通过类加载器【4 种】来获取到类的 Class 对象
//(1)先得到类加载器 car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到 Class 对象
Class<?> cls4 = classLoader.loadClass("com.Class_demo.Car");
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode());
//5. 基本数据(int, char,boolean,float,double,byte,long,short)
// 按如下方式得到 Class 类对象
Class<Integer> cls5 = int.class;
// Class<Double> cls6 = double.class;
//6. 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
Class<Integer> cls6 = Integer.TYPE;
System.out.println(cls5.hashCode());
System.out.println(cls6.hashCode());
}
}
类加载
基本说明
类加载过程图
一、加载阶段 解释
二、连接验证 解释
三、连接准备 解释
四、连接解析 解释
五、初始化 解释
通过反射获取类的结构信息 api
package com.get_struct_info;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author ZhouHao
* @version 1.0
* 成为想成为的人
*/
//通过反射来获取结构信息
public class test_demo {
public static void main(String[] args) {
}
@Test
public void api_01() throws Exception {
Class<?> cls = Class.forName("com.get_struct_info.person");
//getName:获取全类名
System.out.println("全类名:"+cls.getName());
//getSimpleName:获取简单类名
System.out.println("简单类名:"+cls.getSimpleName());
//getFields:获取所有 public 修饰的属性,包含本类以及父类的
Field[] fields = cls.getFields();
System.out.println("本类及父类所有public属性:"+fields);
//getDeclaredFields:获取本类中所有属性
Field[] declaredFields = cls.getDeclaredFields();
System.out.println("本类所有属性:"+declaredFields);
//getMethods:获取所有 public 修饰的方法,包含本类以及父类的
Method[] methods = cls.getMethods();
System.out.println("本类及父类所有public方法:"+methods);
//getDeclaredMethods:获取本类中所有方法
Method[] declaredMethods = cls.getDeclaredMethods();
System.out.println("本类所有方法:"+declaredMethods);
//getConstructors: 获取所有 public 修饰的构造器,包含本类
Constructor<?> constructor = cls.getConstructor();
System.out.println("本类及父类所有public构造器:"+constructor);
//getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
System.out.println("本类所有的构造器:"+declaredConstructors);
//getPackage:以 Package 形式返回 包信息
System.out.println("返回包的信息:"+cls.getPackage());
//getSuperClass:以 Class 形式返回父类信息
System.out.println("返回父类信息:"+cls.getSuperclass());
//getInterfaces:以 Class[]形式返回接口信息
Class<?>[] interfaces = cls.getInterfaces();
System.out.println("返回接口信息:"+interfaces);
//getAnnotations:以 Annotation[] 形式返回注解信息
Annotation[] annotations = cls.getAnnotations();
System.out.println("返回注解信息:"+annotations);
}
@Test
public void api_02() throws ClassNotFoundException {
Class<?> cls = Class.forName("com.get_struct_info.person");
// 以 int的形式返回修饰符
/**默认修饰符 0,public 1, private 2, protected 4, static 8,
* final 16 eg: public(1)+static(8)=9 */
Field[] declaredFields = cls.getDeclaredFields();
for(Field f:declaredFields){
System.out.println("属性名:"+f.getName()+
"属性的修饰符:"+f.getModifiers()+
"属性的类型:"+f.getType());
}
}
@Test
public void api_03() throws ClassNotFoundException {
Class<?> cls = Class.forName("com.get_struct_info.person");
Method[] methods = cls.getDeclaredMethods();
for (Method m:methods){
System.out.println("方法名:"+m.getName()+
"方法的修饰符:"+m.getModifiers()+
"返回类型:"+m.getReturnType()+
"返回参数的数组:"+m.getParameterTypes());
}
}
@Test
public void api_04() throws ClassNotFoundException {
Class<?> cls = Class.forName("com.get_struct_info.person");
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
for (Constructor c:declaredConstructors){
System.out.println("构造器名:"+c.getName()+
"构造器的修饰符:"+c.getModifiers()+
"构造器的参数de数组:"+c.getParameterTypes());
}
}
}
通过反射创建对象实例api
package com.create_new;
import sun.swing.plaf.windows.ClassicSortArrowIcon;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author ZhouHao
* @version 1.0
* 成为想成为的人
*/
//通过class 创建对象实列
public class create_eg {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> cls = Class.forName("com.create_new.user");
//1. 通过 public 的无参构造器创建实例
Object o = cls.newInstance();
System.out.println(o);
//2. 通过 public 的有参构造器创建实例
Constructor<?> constructor = cls.getConstructor(String.class);
Object o1 = constructor.newInstance("小浩纸");
System.out.println(o1);
//3. 通过非 public 的有参构造器创建实例
Constructor<?> constructor1 = cls.getDeclaredConstructor(String.class, int.class);
// 访问私有的会报错 需要爆破
constructor1.setAccessible(true);
Object o2 = constructor1.newInstance("小浩纸~~", 19);
System.out.println(o2);
}
}
通过反射访问类中成员api
package com.反射访问成员;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author ZhouHao
* @version 1.0
* 成为想成为的人
*/
public class demo {
public static void main(String[] args) {
}
// 演示反射来访问成员属性
@Test
public void demo_01()throws Exception{
Class<?> cls = Class.forName("com.反射访问成员.student");
Object o = cls.newInstance();
// 1.获取public属性
Field age = cls.getField("age");
// 给属性设置值
age.set(o, 19);
System.out.println(o);
// 2.操作private 私有的属性
Field name = cls.getDeclaredField("name");
// 私有的话要进行爆破
name.setAccessible(true);
name.set(o,"小浩纸");
// 如果是static 的 o ---> null 可以置空
name.set(null, "小浩纸~");
name.get(null);
System.out.println(o);
}
//---------------------------------------------------------
// 通过反射来访问方法
@Test
public void demo_02()throws Exception{
Class<?> cls = Class.forName("com.反射访问成员.student");
Object o = cls.newInstance();
// 1.访问public方法
Method hi = cls.getMethod("hi", String.class);
hi.invoke(o, "小浩纸~");
// 2.调用私有private方法
Method say = cls.getDeclaredMethod("say", int.class, String.class, char.class);
// 以为私有的 爆破
say.setAccessible(true);
// 因为是static 可以置空
System.out.println(say.invoke(null, 10,"小浩",'男'));
System.out.println(say.invoke(o, 10,"小浩",'男'));
// 在反射中,如果方法有返回值,统一返回 Object ,
// 但是他运行类型和方法定义的返回类型一致
Object invoke = say.invoke(null, 10, "小浩", '男');
System.out.println("运行类型是:"+invoke.getClass()); //String
}
}