声明:以下笔记来源于韩顺平视频https://www.bilibili.com/video/BV1fh411y7R8?p=1,笔记为楼主亲手劳动,劳动不易,转载请标明谢谢。
反射
反射机制
这样的需求在学习框架时
特别多
,即通过外部文件配置,在不修改源码情况下,来控制程序,也符合设计模式的ocp(open cloes principle)原则(开闭原则
:不修改源码,扩容功能) I[开:对工人开放,闭:不允许修改情况请增加功能]反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在
设计模式
和框架底层
都会用到。加载完类之后,在堆中就产生了一个Class类型的对象( 一个类只有一个Class对象) ,这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像一面镜子, 透过这个镜子看到类的结构,所以,形象的称之为:反射
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M0cwf8NB-1648481734475)(D:/Typora%20Data/Img/image-20220325104135681.png)]
public class ReflectionQuestion { public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Properties properties = new Properties(); //因为我的项目不是idea接管的,根目录会从我的C盘开始 properties.load(new FileInputStream("C:\\Users\\86152\\IdeaProjects\\kuangshen-study\\baseLearn\\src\\com\\su\\reflection\\properties_\\re.properties")); String classfullpath = properties.get("classfullpath").toString(); String methodName = properties.getProperty("method"); //引出问题 classfullpath = com.su.reflection.introduce_.Cat Cat cat = new com.su.reflection.introduce_.Cat(); // != Cat cat = new classfullpath();//编译错误 //Class 就是加载类的类 forName 通过类的全路径 Class<?> cls = Class.forName(classfullpath); //newInstance 获得该类一个实例 Object o = cls.newInstance(); //getClass 获得运行时的类型 System.out.println("o的类型 " + o.getClass()); //getMethod 获得方法的实例 在反射中,可以把方法视为对象(万物皆对象) Method methods = cls.getMethod(methodName); // invoke 调用该对象的该方法 methods.invoke(o); } }
发射相关的类
java.lang.Class:代表一个类,Class对象表示某 个类加载后在堆中的对象
java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法对象
java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量对象
java.lang.reflect.Constructor.代表类的构造方法,Constructor对象表示构造器对象
public class Reflection01 { public static void main(String[] args) throws Exception{ Properties properties = new Properties(); properties.load(new FileInputStream("C:\\Users\\86152\\IdeaProjects\\kuangshen-study\\baseLearn\\src\\com\\su\\reflection\\properties_\\re.properties")); String classfullpath = properties.get("classfullpath").toString(); String methodName = properties.getProperty("method"); //Class 就是加载类的类 forName 通过类的全路径 Class<?> cls = Class.forName(classfullpath); //newInstance 获得该类一个实例 Object o = cls.newInstance(); //getClass 获得运行时的类型 System.out.println("o的类型 " + o.getClass()); //getMethod 获得方法的实例 在反射中,可以把方法视为对象(万物皆对象) Method methods = cls.getMethod(methodName); // invoke 调用该对象的该方法 methods.invoke(o); Field ageName = cls.getField("age");//私有属性无法获取 System.out.println(ageName.get(o)); Constructor constructor = cls.getConstructor(); System.out.println(constructor);//无参构造器 Constructor constructor1 = cls.getConstructor(String.class); System.out.println(constructor1);//有参构造器 } }
反射的有缺点
优点:可以
动态的创建和使用对象
(也是框架底层核心),使用灵活没有反射机制,框架技术就失去底层支撑。缺点:使用反射基本是解释执行(会进行安全校验以及同步线程锁),对执行速度有影响.
Method和Field、Constructor对象都有setAccessible()方法(
访问private、protected成员使用
)setAccessible作用是启动和禁用访问安全检查的开关
参数值为true表示反射的对象在使用时取消访问检查,提高反射的效率。参数值为false则表示反射的对象执行访问检查
@SuppressWarnings({"all"}) public class Reflection02 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { m1(); m2(); m3(); } public static void m1(){ Cat cat = new Cat(); long start = System.currentTimeMillis(); for (int i = 0; i < 900000000; i++) { cat.shout(); } long end = System.currentTimeMillis(); System.out.println("传统方式速度 m1=" + (end - start)); } public static void m2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { Class<?> aClass = Class.forName("com.su.reflection.introduce_.Cat"); Object o = aClass.newInstance(); Method shout = aClass.getMethod("shout"); long start = System.currentTimeMillis(); for (int i = 0; i < 900000000; i++) { shout.invoke(o); } long end = System.currentTimeMillis(); System.out.println("反射方式速度 m2=" + (end - start)); } public static void m3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { Class<?> aClass = Class.forName("com.su.reflection.introduce_.Cat"); Object o = aClass.newInstance(); Method shout = aClass.getMethod("shout"); shout.setAccessible(true); long start = System.currentTimeMillis(); for (int i = 0; i < 900000000; i++) { shout.invoke(o); } long end = System.currentTimeMillis(); System.out.println("反射方式(关闭访问检查)速度 m3=" + (end - start)); } }
Class 类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vSTrjTRx-1648481734480)(D:/Typora%20Data/Img/image-20220325154156680.png)]
Class也是类,因此也继承Object类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Npn9AYq1-1648481734481)(D:/Typora%20Data/Img/image-20220325154242717.png)]
Class类对象不是new出来的,而是系统创建的
对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
每个类的实例都会记得自己是由哪个Class实例所生成
通过Class对象可以完整地得到一个类的完整结构, 通过一系列APIClass对象是存放在堆的
类的字节码二进制数据,是放在方法区的,有的地方称为
类的元数据
(包括方法代码,变量名,方法名,访问权限等等) https://www.zhihu.com/question/38496907
Class 类常用方法
public class Class02 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { String classAllPath = "com.su.reflection.introduce_.Car"; //forName 获取到Car类对应的Class对象(非实例) <?> 表示不确定类型 Class<?> cls = Class.forName(classAllPath); System.out.println(cls);//显示cls对象,是那个类的Class对象 System.out.println(cls.getClass());//输出cls的预习类型 java.lang.Class //getPackage().getName() 获取包名 System.out.println(cls.getPackage().getName()); //getName 获取全类名 System.out.println(cls.getName()); // newInstance 创建对象实例 Car car = (Car)cls.newInstance(); System.out.println(car); //getField 反射获取属性 brand 实例 Field brand = cls.getField("brand"); System.out.println(brand.get(car)); //set 通过反射给 brand 注入值 brand.set(car,"宝马"); System.out.println(brand.get(car)); // getFields 获取所有属性 Field[] fields = cls.getFields(); for (Field f : fields) { System.out.println(f.getName()); } } }
获取 Class 对象
前提:已知
一个类的全类名
,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException, 实例: Class cls1 = Class.forName( “java.lang.Cat” );应用场景:多用于配置文件,读取类全路径,加载类.
前提:若
已知具体的类
,通过类的class获取,该方式最为安全可靠,程序性能最高实例:Class cls2 = Cat.class;应用场景:多用于参数传递,比如通过反射得到对应构造器对象.
前提:已知
某个类的实例
,调用该实例的getClass(方法获取Class对象,实例:
Class clazz =对象.getClass();//运行类型
应用场景:通过创建好的对象,获取Class对象.其他方式
getClassLoader
ClassLoader cl =对象.getClass(.getClassLoader(;
Class clazz4 = cl.loadClass(“类的全类名”);基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象
Class cls =基本数据类型.class基本数据类型对应的包装类,可以通过.TYPE得到Class类对象
Class cls =包装类.TYPEpublic class GetClass { public static void main(String[] args) throws ClassNotFoundException { String classAllPath = "com.su.reflection.introduce_.Car"; //编译阶段 Class<?> cls1 = Class.forName(classAllPath); System.out.println(cls1); //加载阶段 Class<Car> cls2 = Car.class; System.out.println(cls2); //运行阶段 Car car = new Car(); Class cls3 = car.getClass(); //加载器ClassLoader ClassLoader classLoader = car.getClass().getClassLoader(); Class<?> cls4 = classLoader.loadClass(classAllPath); System.out.println(cls4); // cls1 cls2 cls3 cls4 为同一个类型,同一个Class对象 System.out.println(cls1.hashCode()); System.out.println(cls2.hashCode()); System.out.println(cls3.hashCode()); System.out.println(cls4.hashCode()); //基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象 Class<Integer> integerClass = int.class; Class<Character> characterClass = char.class; System.out.println(integerClass); //基本数据类型对应的包装类,可以通过.TYPE得到Class类对象 Class<Integer> type1 = Integer.TYPE; Class<Boolean> type2 = Boolean.TYPE; System.out.println(type1); System.out.println(integerClass.hashCode()); System.out.println(type1.hashCode()); System.out.println(type1.hashCode() == integerClass.hashCode());//true } }
有 Class 对象的数据类型
外部类,成员内部类,静态内部类,局部内部类,匿名内部类
interface :接口
数组
enum:枚举
annotation :注解
基本数据类型
void
public class AllTypeClass { public static void main(String[] args) { Class<String> cls1 = String.class;//外部类 Class<Serializable> cls2 = Serializable.class;//接口 Class<Integer[]> cls3 = Integer[].class;//数组 Class<float[][]> cls4 = float[][].class;//二维数组 Class<Deprecated> cls5 = Deprecated.class;//注解 Class<Thread.State> cls6 = Thread.State.class;//枚举 Class<Long> cls7 = long.class;//基本数据类型 Class<Integer> cls8 = Integer.TYPE;//包装类 Class<Void> cls9 = void.class;//空类型 Class<Class> cls10 = Class.class;//Class类本身 System.out.println(cls1); System.out.println(cls2); System.out.println(cls3); System.out.println(cls4); System.out.println(cls5); System.out.println(cls6); System.out.println(cls7); System.out.println(cls8); System.out.println(cls9); System.out.println(cls10); } }
动态与静态加载
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
Cat cat = new Cat();//静态加载
动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性.
Class cls = Class.forName("Person");//动态加载
类加载时机
- 当创建对象时(new) //静态加载
- 当子类被加载时,父类也加载//静态加载
- 调用类中的静态成员时//静态加载
- 通过反射//动态加载
类加载流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZldKNIj-1648481734482)(D:/Typora%20Data/Img/image-20220326094025505.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-efnRRq2u-1648481734482)(D:/Typora%20Data/Img/image-20220326094222550.png)]
类加载的五个阶段
一、加载阶段
JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转化为
二进制字节流
加载到内存中,并生成
一个代表该类的java.lang.Class对象
二、连接阶段-验证
- 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
- 包括:
文件格式
验证(是否以 魔数 oxcafe babe开头)、元数据
验证、字节码
验证和符号引用
验证- 可以考虑使用-
Xverify:none
参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
三、连接阶段-准备
JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0、0L、null、 false 等)。这些变量所使用的内存都将在方法区中进行分配。
class A { public int n1 = 10;//实例变量不会,加载阶段不会初始化 public static int n2 = 20;//静态变量,加载会默认初始化为0 public static finil int n3 = 30;//静态常量,不会改变,加载阶段会自己分配空间赋值30 }
四、连接阶段-解析
虚拟机将常量池内的
符号引用
(没有内存地址表示时的形式,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可)替换为直接引用
(可以用内存地址表示的引用,比如直接指向目标的指针)的过程。https://www.cnblogs.com/shinubi/articles/6116993.html[详细的jvm符号引用与直接引用]
五、初始化-Initialization
- 到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行 ()方法的过程。
- (0)方法是由编译器按语句在源文件中出现的顺序,
依次自动收集
类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并
。- 虚拟机会保证一个类的< clinit> 0)方法在多线程环境中被正确地
加锁、同步
,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的 )方法,其他线程都需要阻塞等待,直到活动线程执行 )方法完毕.
获取类结构信息
第一组:java.lang.Class 类
getName:获取全类名
getSimpleName:获取简单类名
getFields:获取所有public修饰的属性,包含本类以及父类的
getDeclaredFields:获取本类中所有属性
getMethods:获取所有public修饰的方法,包含本类以及父类的
getDeclaredMethods:获取本类中所有方法
getConstructors:获取所有public修饰的构造器,
包含本类
getDeclaredConstructors:获取本类中所有构造器
getPackage:以Package形式返回包信息
getSuperClass:以Class形式返回父类信息
getInterfaces:以Class[]形式返回接口信息
getAnnotations:以Annotation[形式返回注解信息
public class ReflectUtils_ { public static void main(String[] args) { } @Test public void api_01() throws ClassNotFoundException { Class cls = Class.forName("com.su.reflection.introduce_.Persion"); // 1. getName:获取全类名 System.out.println("=========================="); System.out.println(cls.getName()); // 2. getSimpleName:获取简单类名 System.out.println("=========================="); System.out.println(cls.getSimpleName()); // 3. getFields:获取所有public修饰的属性,包含本类以及父类的 System.out.println("=========================="); Field[] fields = cls.getFields(); for (Field field : fields) { System.out.println(field.getName()); } // 4. getDeclaredFields:获取本类中所有属性 System.out.println("=========================="); Field[] declaredFields = cls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } // 5. getMethods:获取所有public修饰的方法,包含本类以及父类的 System.out.println("=========================="); Method[] methods = cls.getMethods(); for (Method method : methods) { System.out.println(method); } // 6. getDeclaredMethods:获取本类中所有方法 System.out.println("=========================="); Method[] declaredMethods = cls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } // 7. getConstructors:获取所有public修饰的构造器,包含本类 System.out.println("=========================="); Constructor[] constructors = cls.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } // 8. getDeclaredConstructors:获取本类中所有构造器 System.out.println("=========================="); Constructor[] declaredConstructors = cls.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } // 9. getPackage:以Package形式返回包信息 System.out.println("=========================="); System.out.println(cls.getPackage()); // 10. getSuperClass:以Class形式返回父类信息 System.out.println("=========================="); System.out.println(cls.getSuperclass()); // 11. getInterfaces:以Class[]形式返回接口信息 System.out.println("=========================="); Class[] interfaces = cls.getInterfaces(); for (Class anInterface : interfaces) { System.out.println(anInterface); } // 12. getAnnotations:以Annotation[形式返回注解信息 System.out.println("=========================="); Annotation[] annotations = cls.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } } } class A{ public String hoppy; public A(){} public void hi(){} private void say(){} } interface IA {} interface IB {} @Deprecated class Persion extends A implements IA,IB{ public String name; protected int age; String job; private double sal; public Persion(){} public Persion(String name){this.name = name;} private Persion(String name, int age){} public void m1(){} protected void m2(){} void m3(){} private void m4(){} }
第二组:java.lang.reflect.Field 类
getModifiers:以int形式返回修饰符
[说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final 是16]public(1) + static(8) = 9
getType:以Class形式返回类型
getName:返回属性名
@Test public void api_02() throws ClassNotFoundException { Class cls = Class.forName("com.su.reflection.introduce_.Persion"); System.out.println("=========================="); Field[] declaredFields = cls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("属性" + declaredField + "修饰符值" + declaredField.getModifiers() +"属性类型" + declaredField.getType()); } // 6. getDeclaredMethods:获取本类中所有方法 System.out.println("=========================="); Method[] declaredMethods = cls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("属性" + declaredMethod + "修饰符值" + declaredMethod.getModifiers() +"返回值类型" + declaredMethod.getReturnType()); Class<?>[] parameterTypes = declaredMethod.getParameterTypes(); for (Class<?> parameterType : parameterTypes) { System.out.println("形参类型" + parameterType); } } // 8. getDeclaredConstructors:获取本类中所有构造器 System.out.println("=========================="); Constructor[] declaredConstructors = cls.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); System.out.println("=========================="); Class[] parameterTypes = declaredConstructor.getParameterTypes(); for (Class parameterType : parameterTypes) { System.out.println(parameterType); } } }
第三组:java.lang.reflect.Method类
getModifiers:以in形式返回修饰符
[说明:默认修饰符是0 , public 是1,private是2,protected是4,static是8,final 是16]getReturnType:以Class形式获取返回类型
getName:返回方法名
getParameterTypes:以Class[]返回参数类型数组
@Test public void api_02() throws ClassNotFoundException { Class cls = Class.forName("com.su.reflection.introduce_.Persion"); System.out.println("=========================="); Field[] declaredFields = cls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("属性" + declaredField + "修饰符值" + declaredField.getModifiers() +"属性类型" + declaredField.getType()); } // 6. getDeclaredMethods:获取本类中所有方法 System.out.println("=========================="); Method[] declaredMethods = cls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("属性" + declaredMethod + "修饰符值" + declaredMethod.getModifiers() +"返回值类型" + declaredMethod.getReturnType()); Class<?>[] parameterTypes = declaredMethod.getParameterTypes(); for (Class<?> parameterType : parameterTypes) { System.out.println("形参类型" + parameterType); } } // 8. getDeclaredConstructors:获取本类中所有构造器 System.out.println("=========================="); Constructor[] declaredConstructors = cls.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); System.out.println("=========================="); Class[] parameterTypes = declaredConstructor.getParameterTypes(); for (Class parameterType : parameterTypes) { System.out.println(parameterType); } } }
第四组:java.lang.reflect.Constructor类
getModifiers:以int形式返回修饰符
getName:返回构造器名(全类名)
getParameterTypes:以Class[]返回参数类型数组
@Test public void api_02() throws ClassNotFoundException { Class cls = Class.forName("com.su.reflection.introduce_.Persion"); System.out.println("=========================="); Field[] declaredFields = cls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("属性" + declaredField + "修饰符值" + declaredField.getModifiers() +"属性类型" + declaredField.getType()); } // 6. getDeclaredMethods:获取本类中所有方法 System.out.println("=========================="); Method[] declaredMethods = cls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("属性" + declaredMethod + "修饰符值" + declaredMethod.getModifiers() +"返回值类型" + declaredMethod.getReturnType()); Class<?>[] parameterTypes = declaredMethod.getParameterTypes(); for (Class<?> parameterType : parameterTypes) { System.out.println("形参类型" + parameterType); } } // 8. getDeclaredConstructors:获取本类中所有构造器 System.out.println("=========================="); Constructor[] declaredConstructors = cls.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); System.out.println("=========================="); Class[] parameterTypes = declaredConstructor.getParameterTypes(); for (Class parameterType : parameterTypes) { System.out.println(parameterType); } } }
通过反射创建对象
方式-: 调用类中的public修饰的无参构造器
方式二:调用类中的指定构造器
Class类相关方法
- newInstance :调用类中的无参构造器,获取对应类的对象
- getConstructor(Class…class):根据参数列表,获取对应的构造器对象
- getDecalaredConstructor(Class…class):根据参数列表,获取对应的构造器对象
Constructor类相关方法
- setAccessible:暴破[暴力破解]
- newlnstance(Object…obj):调用构造器
public class ReflectCreateInstance { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class<?> cls = Class.forName("com.su.reflection.introduce_.User"); //通过newInstance创造对象 Object o = cls.newInstance(); System.out.println(o); //通过public 构造器创建实例 Constructor<?> constructor = cls.getConstructor(String.class); Object o1 = constructor.newInstance("孙悟空"); System.out.println(o1); //通过private 构造器创建实例 Constructor<?> declaredConstructor = cls.getDeclaredConstructor(String.class, int.class); //暴破[暴力破解] //使用反射可以访问private构造器/方法/属性,反射面前,都是纸老虎 declaredConstructor.setAccessible(true); Object o2 = declaredConstructor.newInstance("紫霞仙子", 18); System.out.println(o2); } } class User { private String name = "菩提老祖"; private int age = 100; public User() { } public User(String name) { this.name = name; } private User(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
通过反射访问类中的成员
根据属性名获取Field对象
Field f = class对象.getDeclaredField(属性名);暴破: f.setAccessible(true); //f是Field
访问
f.set(o,值);
syso(f.get(o));如果是静态属性,则set和get中的参数o,可以写成null
public class ReflectAccessProperty { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { Class<?> cls = Class.forName("com.su.reflection.introduce_.Student"); Object o = cls.newInstance(); System.out.println(o.getClass());//运行类型 System.out.println("============================="); Field age = cls.getField("age"); System.out.println(age); age.set(o, 88); System.out.println(age.get(o)); System.out.println("============================="); Field name = cls.getDeclaredField("name"); name.setAccessible(true); // name.set(o,"代付"); name.set(null,"代付"); System.out.println(o); System.out.println(name.get(o)); System.out.println(name.get(null));//要求属性必须为static } } class Student { private static String name; public int age; public Student() { } @Override public String toString() { return "Student{" + "age=" + age + " name=" + name + '}'; } }
通过反射访问类中的方法
根据方法名和参数列表获取Method方法对象: Method m = clazz.getDeclaredMethod(方法名,XX.class); //得到本类的所有方法
获取对象: Object o=clazz.newlnstance();
暴破: m.setAccessible(true);
访问: Object returnValue = m.invoke(o,实参列表);//o就是对象
注意:如果是静态方法,则invoke的参数o, 可以写成null!
public class ReflectAccessMethod { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class<?> cls = Class.forName("com.su.reflection.introduce_.Boss"); Object o = cls.newInstance(); System.out.println("==========================="); Method hi = cls.getDeclaredMethod("hi", String.class); hi.invoke(o, "有点迷茫"); System.out.println("==========================="); Method say = cls.getDeclaredMethod("say", int.class, String.class, char.class); say.setAccessible(true); System.out.println(say.invoke(o, 100, "张三", '男')); System.out.println(say.invoke(null, 300, "李四", '女')); } } class Boss { private static String name; public int age; public Boss() { } private static String say(int n, String s, char c) { return n + " " + s + " " + c + " "; } public void hi(String s) { System.out.println("hi " + s); } }
反射的总结
729 https://www.bilibili.com/video/BV1fh411y7R8?p=730