免费网站建设优化,设计用哪些网站,网站建设的市场调研分析,教育类企业网站反射 是 Java框架 的核心 #xff0c;无论是Tomcat、SpringMVC、Spring IOC、Spring AOP、动态代理 #xff0c;都使用到了 反射
反射的作用简单讲就是 无需 new 对象#xff0c;就可以动态获取到一个类的全部信息#xff0c;包括 属性、方法#xff0c;构造器#xff0…反射 是 Java框架 的核心 无论是Tomcat、SpringMVC、Spring IOC、Spring AOP、动态代理 都使用到了 反射
反射的作用简单讲就是 无需 new 对象就可以动态获取到一个类的全部信息包括 属性、方法构造器以及他们的修饰符、参数、注解 等等... 从而构造出 对象实例 并对 对象实例 进行操作
因此学好反射是必须的接下来就学习如何使用反射
这是我们下面要进行操作的类
public class Student {private String name;private int age;public String gender;public String address;public Student() {}public Student(String name, int age, String address) {this.name name;this.age age;this.address address;}public Student(String name, int age, String gender, String address) {this.name name;this.age age;this.gender gender;this.address address;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender gender;}public String getAddress() {return address;}public void setAddress(String address) {this.address address;}private void study(){System.out.println(学生在学习);}private void sleep(){System.out.println(学生在睡觉);}public String eat(String something){System.out.println(学生在吃 something);return 学生已经吃完了非常happy;}public String toString() {return Student{name name , age age , gender gender , address address };}
}获取字节码文件对象即 类对象的三种方式
通过 Class类 里面的 静态方法forName(全类名)最常用通过 类名.class 属性获取通过对象获取字节码文件对象 -- 对象名.getClass()
什么是字节码文件对象
java文件就是我们自己编写的java代码。
字节码文件就是通过java文件编译之后的class文件是在硬盘上真实存在的用眼睛能看到的
字节码文件对象当class文件加载到内存之后虚拟机自动创建出来的对象。这个对象里面就包含了类的所有信息。并且该对象在内存中是唯一的存在于 JVM 的方法区中
往后 获取类信息 的操作都是建立在 字节码文件对象 的基础上的
这三种获取 字节码文件对象 的方法是有区别的
Class.forName(全类名) -- 在 java文件阶段 就可以获取 字节码文件对象因此这是最常用的类名.class -- 要在 类加载完成阶段 才能获取对象名.getClass) -- 要在 对象已经被创建出来的阶段 才能获取
代码示例
//第一种方法
Class clazz1 Class.forName(com.zhuyuanjie.reflectdemo.Student);//第二种方法
Class clazz2 Student.class;//第三种方法
Student s new Student();
Class clazz3 s.getClass();
System.out.println(clazz1 clazz2);//true
System.out.println(clazz2 clazz3);//true获取 构造方法 并使用
不许通过 new 我们也能通过反射获取到实例对象
大致步骤 -- 获取构造器对象调用构造器的 newInstance 方法就可以创建出实例对象
——— 1.首先获取构造器对象 ————
方法如下
方法名说明Constructor?[] getConstructors()获得所有的构造只能public修饰Constructor?[] getDeclaredConstructors()获得所有的构造包含private修饰Constructor getConstructor(Class?... parameterTypes)获取指定构造只能public修饰Constructor getDeclaredConstructor(Class?... parameterTypes)获取指定构造包含private修饰
观察上面表格发现方法中如果没加 Declareed 就只能获取 public 的构造方法而加了 Declareed 就可以获取全部
而且方法末尾如果有 s 是获取所有没加 s 是获取指定的构造器需传入 指定构造器的参数列表
代码实例 //获得class字节码文件对象Class clazz Class.forName(com.zhuyuanjie.reflectdemo.Student);//获取构造方法对象//获取所有构造方法publicConstructor[] constructors1 clazz.getConstructors();for (Constructor constructor : constructors1) {System.out.println(constructor);}//获取指定的空参构造Constructor con1 clazz.getConstructor();System.out.println(con1);//获取带参数的构造方法Constructor con2 clazz.getDeclaredConstructor(String.class);System.out.println(con2);——— 2 调用 newInstance 方法创建 实例对象———
//1.获取整体的字节码文件对象
Class clazz Class.forName(com.zhuyuanjie.reflectdemo.Student);
//2.获取空参的构造方法
Constructor con clazz.getConstructor();
//3.利用空参构造方法创建对象
Student stu (Student) con.newInstance();
System.out.println(stu);上面代码中如果我们获取到的构造方法是 private 属性那么我们还不能直接调用需要调用 setAccessible(true)方法 传入参数 true来临时取消访问权限如下
Class clazz Class.forName(com.zhuyuanjie.reflectdemo1.Student);Constructor con clazz.getConstructor();//调用 setAccessible(true) 方法
con.setAccessible(true);Student stu (Student) con.newInstance();
System.out.println(stu);该方法不止用在构造方法上包括接下来的 属性、方法 等只要对 private修饰 的进行操作就需要调用
获取 成员变量属性 并使用
方法名说明Field[] getFields()返回所有成员变量对象的数组只能拿public的Field[] getDeclaredFields()返回所有成员变量对象的数组存在就能拿到Field getField(String name)返回单个成员变量对象只能拿public的Field getDeclaredField(String name)返回单个成员变量对象存在就能拿到
可以发现以上方法名的结构与 获取构造方法使用到的方法 一样这里不在赘述
代码实例
//1.获取class对象Class clazz Class.forName(com.zhuyuanjie.reflectdemo.Student);//获取成员变量的对象public privateField[] fields2 clazz.getDeclaredFields();for (Field field : fields2) {System.out.println(field);}System.out.println();//获得单个成员变量对象//如果获取的属性是不存在的那么会报异常//Field field3 clazz.getField(aaa);//System.out.println(field3);//NoSuchFieldExceptionSystem.out.println();//获取单个成员变量私有Field field5 clazz.getDeclaredField(name);System.out.println(field5);获取到 Field 对象后我们就能得到 成员变量 的一切信息
//1.获取class对象Class clazz Class.forName(com.zhuyuanjie.reflectdemo.Student);Field name clazz.getDeclaredField(name);//临时取消访问权限name.setAccessible(true);//获取权限修饰符int modifiers name.getModifiers(); //2//获取属性名String n name.getName(); // name//获取数据类型Class? type name.getType(); //class java.lang.String//等等... 还有很多不在展示
还可以获取和修改 成员变量 的值
方法说明void set(Object obj, Object value赋值Object get(Object obj)获取值 Class clazz Class.forName(com.zhuyuanjie.reflectdemo.Student);Field field clazz.getDeclaredField(name);field.setAccessible(true);//设置(修改)name的值//参数一表示要修改哪个对象的name//参数二表示要修改为多少field.set(s,张三);//获取name的值//表示我要获取这个对象的name的值String result (String)field.get(s); // 张三获取 成员方法 并运行
获取 成员方法 的方法和获取 成员的变量 的方法几乎一样就是把 Field 改为 Method
而 获取到 成员方法 后通过调用 Object invoke(Object obj, Object... args) 进行运行
其中
参数一用obj对象调用该方法
参数二调用方法的传递的参数如果没有就不写 //1.获取字节码文件对象Class clazz Class.forName(com.zhuyuanjie.reflectdemo.Student);//2.获取一个对象//需要用这个对象去调用方法Student s new Student();//3.获取一个指定的方法//参数一方法名//参数二参数列表如果没有可以不写Method eatMethod clazz.getMethod(eat,String.class);//运行//参数一表示方法的调用对象//参数二方法在运行时需要的实际参数//注意点如果方法有返回值那么需要接收invoke的结果//如果方法没有返回值则不需要接收String result (String) eatMethod.invoke(s, 重庆小面);System.out.println(result);同样的如果方法是 private 也需要调用 setAccessible(true) 方法
除了以上最常用的获取 构造方法 、成员变量 、成员方法 在框架中还经常通过反射获取 类 、 属性 、方法 上的注解信息
有需要可以看我的另外一篇博客地址
http://t.csdn.cn/qyDp0http://t.csdn.cn/qyDp0
而且我的 Gitee 上有 Tomcat 、SpringMVC 等框架的核心源码仿写可以感受下反射在框架中的使用Gitee 地址如下
朱元杰的Gitee -- 框架源码仿写https://gitee.com/Speed_Demon/projects