Java反射
获取Class对象
命令 | 解释 |
---|---|
Class cls = Class.forName(“java.lang.Cat”) | 多用于配置文件,读取类全路径,加载类 |
Class cls = Cat.class | 多用于参数传递 |
Class cls = 对象.getClass() | 通过创建好的对象,获取Class对象 |
ClassLoader cl = 对象.getClass().getClassLoader() Class cls = cl.loadClass(“类的全类名”) | 通过类加载器获得 |
Class cls = 基本数据类型.class | 获取基本数据类型的class对象 |
Class cls = 包装类.TYPE | 获得包装类的Class对象 |
Class对象的基础命令
命令 | 解释 |
---|---|
cls.getName() | 获取对象的名词 |
cls.getSimpleName() | 获取简单类名 |
cls.getPackage().gameName() | 获取类对象包名 |
cls.getSupercls().getName() | 获取类对象父类 |
cls.getInterfaces() | 获取类对象接口 |
cls.getSuperClass | 以Class形式返回父类信息 |
cls.getInterfaces | 以Class[]形式返回接口信息 |
cls.getAnnotations | 以Annotation[]形式返回注解信息 |
获取构造方法
命令 | 解释 |
---|---|
cls.getConstructors() | 获取类对象所有的构造方法 |
cls.DeclaredConstructors | 获取本类中所有方法 |
cls.getConstructor() | 获取类对象的无参构造 |
cls.newInstance() | 使用无参构造创建一个对象 |
cls.getConstructor(String.cls,int cls) | 获取类中的带参构造 |
cls.newInstance(“王五”,20) | 使用有参构造创建一个对象 |
constructor.getModifiers | 以int形式返回修饰符 |
constructor.getName | 返回构造器名(全类名) |
constructor.getParameterTypes | 以Class[]返回参数类型数组 |
获取属性
命令 | 解释 |
---|---|
cls.getField() | 获取属性(字段)公开的字段,父类继承的字段 |
cls.getDeclaredFirelds() | 获取所有属性包括私有,默认,保护 |
cls.getFields(“name”) | 获取单一属性(name为属性名) |
Field namefield = cls.getFields(“name”) Person p = (Person)cls.newInstance() namefield.set(p,“张三”) | 赋值/修改属性的值 |
Field namefield = cls.getFields(“name”) Person p = (Person)cls.newInstance() namefield.get( p ) | 获取属性的值 |
field.getName() | 返回属性名 |
field.getType() | 以Class形式返回类型 |
field.getModifiers | 以int形式返回修饰符 |
获取方法 | |
命令 | 解释 |
-------- | ----- |
cls.getMethods() | 获取公开的方法和父类继承的方法 |
cls.getDeclaredMethods() | 获取公开的方法和私有方法,不能获取父类继承的方法 |
cls.getMethod(“eat”) | 获取无参方法 |
cls.getMethod(“eat”,String.cls) | 获取带参方法 |
cls.getDeclaredMethod() | 获取私有方法 |
Method eatMethod = cls.getMethod(“eat”) eaMethod.invoke(zhangsan) | 执行无参方法 zhangsan,eat(); |
Method eatMethod = cls.getMethod(“eat”,String.cls) eaMethod.invoke(zhangsan,“香蕉”) | 执行带参方法 zhangsan.eat(“香蕉”) |
Method eatMethod = cls.getMethod(“eat”) eatMethod.invoke(null) | 执行无参静态方法 Person.eat() |
Method eatMethod = cls.getMethod(“eat”,String.cls) eaMethod.invoke(null,“香蕉”) | 执行带参静态方法 Person.eat(“香蕉”) |
method.getReturnType() | 以Class形式获取返回类型 |
method.getName() | 返回方法名 |
method.getParameterTypes | 以Class[]返回参数类型数组 |
爆破
命令 | 解释 |
---|---|
construcrtor.setAccessible(true) | 使反射可以访问private构造器 |
field.setAccessible(true) | 使反射可以访问private属性 |
method.setAccessible(true) | 使反射可以访问private方法 |
获取对象
//获取对象
//无参直接获取
Person p = (Person) aClass.newInstance();
//带参,先指定参数类型
Constructor<?> constructor = aClass.getConstructor(String.class, int.class);
Person p2 = (Person) constructor.newInstance("王五", 20);
获取属性
//获取属性
Field name = aClass.getDeclaredField("name");
//如果是私有属性,需要爆破
name.setAccessible(true);
name.set(p2, "李四");
System.out.println(name.get(p2));
Field job = aClass.getDeclaredField("job");
job.setAccessible(true);
//如果是静态属性,可以不指定对象
job.set(null, "程序员");
System.out.println(job.get(p2));
获取方法
//获取方法
Method t1 = aClass.getDeclaredMethod("t1");
t1.invoke(p2);
//带参方法
Method t2 = aClass.getDeclaredMethod("t2", String.class, int.class);
t2.invoke(p2, "小明", 30);
什么是反射
反射常用类
反射的优缺点
Class类
1.Class也是类,因此也继承Object类
2.Class对象不是new出来的,而是系统创建的
在加载阶段,就会在堆中创建类对象
3.对于某个类的Class类对象,在内存那种只有一份,因为类只加载一次
Class对象相当于一个模板
Class类常用方法
获取Class的名字、包名、父类、接口
获取Class的构造方法并使用
获取Class属性
获取Class的方法
获取类的所有方法
获取类的单一方法
使用反射实现一个可以调用任何对象方法的通用方法
Class对象
获取Class对象的六种方式
类加载
类加载流程
加载阶段
验证
准备
解析
符号引用转换为内存地址引用
初始化
获取类结构信息
通过反射创建对象
通过反射操作属性
通过反射操作方法
练习
反射调用优化