为什么要学习反射?
反射可以动态创建对象以及获取对应的对象属性 方法,从而让代码更灵活不必写死,好多框架必不可少的使用了反射机制,同时反射机制也符合OCP(开闭原则)即在不修改源码的情况下,进行操作 看上边估计你可能印象不怎么大下边我举个栗子你就能感受到灵活的好处了。
反射可以做什么?
已知反射机制的特点后我们可以用反射机制来做个“状态机”,即根据时间来进行状态流转
以上只是简单的介绍了下反射机制可以做什么,需要了解详细的可以和博主私聊讨论哦~
一个需求引出反射
1、根据配置文件re.properties指定信息,创建Cat对象并调用方法hi
- classfullpath=com.hspedy.Cat
- method=hi
- package com.shb.reflection.question;
-
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.Properties;
-
- /**
- * 反射问题引入
- */
- public class ReflectionQuestion {
-
- public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
- //根据配置文件re.properties指定信息,创建Cat对象并调用方法hi
-
- //传统方式 new 对象 -》调用其方法
- /* Cat cat = new Cat();
- cat.hi();*/
-
- //文件流方式 Properties
- //1、取出配置文件值
- Properties properties = new Properties();
- properties.load(new FileInputStream("/Users/ext.songhaibo/IdeaProjects/Reflection/src/main/resources/re.properties"));
- String classfullpath = properties.get("classfullpath").toString();
- String methodName = properties.get("method").toString();
- System.out.println("classfullpath = " + classfullpath);
- System.out.println("methodName = " + methodName);
- //2、创建对象 传统的方法已经不行了
- // new classfullpath();
-
- //反射模式符合开闭原则 OCP,即在不修改源码的情况下,进行操作
-
- //3、传统模式下解决不了就用反射机制
- //(1)加载class类 返回Class对象
- Class<?> cls = Class.forName(classfullpath);
- //(2)通过 cls 得到加载类 com.shb.Cat的对象实例
- Object o = cls.newInstance();
- System.out.println(o.getClass());
- //(3)通过 cls 得到加载的类的com.shb.Cat类的methodName"hi"的对象
- //即:在反射中,可以把方法视为对象(万物皆对象)
- Method method = cls.getMethod(methodName);
- //通过method来调用方法,即通过方法对象来调用方法
- method.invoke(o);//传统方式 对象.方法 反射机制 方法.invoke(对象)
-
- }
- }
1.反射机制允程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到
2.加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为反射

- java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
-
- java.lang.reflect.Method:代表类的方法
-
- java.lang.reflect.Field:代表类的成员变量
-
- java.lang.reflect.Constructor:代表类的构造方法
-
- 这些类在java.lang.reflect :提供用于获取关于类和对象的反射信息的类和接口
优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就是失去底层支撑。
缺点:使用反射基本是解释执行,对执行速度有影响。
例子:Reflection02.java
- public class Reflection02 {
-
- public static void main(String[] args) throws Exception {
- m1();
- m2();
- }
-
- //普通方法调用hi
- public static void m1() {
-
- Cat cat = new Cat();
- long start = System.currentTimeMillis();
- for (int i = 0; i < 900000000; i++) {
- cat.hi();
- }
- long end = System.currentTimeMillis();
- System.out.println("普通方法调用hi 耗时 " + (end - start));
-
- }
-
- //反射机制调用hi
- public static void m2() throws Exception {
- //(1)加载class类 返回Class对象
- Class<?> cls = Class.forName("com.shb.Cat");
- Object o = cls.newInstance();
- long start = System.currentTimeMillis();
- Method method = cls.getMethod("hi");
- for (int i = 0; i < 900000000; i++) {
- method.invoke(o);//传统方式 对象.方法 反射机制 方法.invoke(对象)
- }
- long end = System.currentTimeMillis();
- System.out.println("反射机制调用hi 耗时 " + (end - start));
-
- }
- /**
- * Class常用api示例
- */
- public class ClassApi {
- public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
- String classAllPath = "com.shb.Car";
- //1、获取Car类对象
- Class<?> cls = Class.forName(classAllPath);
- //2、输出cls
- System.out.println(cls); //是哪个类型 cls
- System.out.println(cls.getClass()); //运行类型
- //3、获取包名
- System.out.println(cls.getPackage().getName());
- //4、获取全类名
- System.out.println(cls.getName());
- //5、生成对象实例
- Object o = cls.newInstance();
- Car car = (Car) o;
- System.out.println(car);
- //6、通过反射获取属性 不能获取私有属性
- Field brand = cls.getField("brand");
- System.out.println(brand.get(car));
- //7、通过反射给属性设置值
- brand.set(car, "奥迪");
- System.out.println(brand.get(car));
- //8、得到所有的属性 只能得到公共的
- Field[] fields = cls.getFields();
- for (Field field : fields) {
- System.out.println(field.toString());
- }
- //9、得到所有的属性包括私有的 getDeclaredFields
- for (Field declaredField : cls.getDeclaredFields()) {
- System.out.println(declaredField.toString());
- }
-
- }
- 1. 前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取。
- ○ 应用场景:多用于配置文件,读取类全路径,加载类。
- ○ 阶段:代码阶段/编译阶段 Class.forName()
- 2. 前提:若已知具体的类,通过类的class获取,该方式 最为安全可靠,程序性能最高实例:Class cls=Cat.class;
- ○ 应用场景:多用于参数传递,比如通过反射得到对应构造器对象。
- ○ 阶段:加载阶段 类.class
- 3. 前提:已知某个类的实例,调用改实例的getClass()方法获取Class对象,实例:Class class= 对象.getClass();
- ○ 应用场景:通过创建好的对象,获取Class对象。
- ○ 阶段:运行阶段 对象.getClass()
- 4. 其他方式 类加载器 得到Class对象
- ○ ClassLoader cl=对象.getClass().getClassLoader();
- ○ Class clazz4=cl.loadClass("类的全类名");
- 5. 基本数据类型得到Class对象
- ○ Class cls= 基本数据类型.class
- ○ 阶段:加载阶段 类.class
- 6. 基本数据类型对应的包装类,可以通过.type得到Class类对象
- ○ Class cls=包装类.TYPE
- ○ 阶段:加载阶段 类.class
ClassLoad.java com.shb.classload
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
Class.froName("com.shb.Cat");






com.shb.reflection ReflectionUtils
- package com.shb.reflection;
-
- import org.junit.Test;
-
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
-
- /**
- * 通过反射获取类的结构信息 API
- */
- public class ReflectionUtils {
- public static void main(String[] args) {
-
- }
-
- @Test
- // 第一组:java.lang.Class类
- public void api_01() throws ClassNotFoundException {
- //得到Class对象
- Class<?> personClass = Class.forName("com.shb.reflection.Person");
- // 1. getName:获取全类名
- System.out.println(personClass.getName());
- // 2. getSimpleName:获取简单类名
- System.out.println(personClass.getSimpleName());
- // 3. getFields:获取所有public修饰的属性,包含本类以及父类的
- for (Field field : personClass.getFields()) {
- System.out.println(field.getName());
- }
- // 4. getDeclaredFields:获取本类中所有属性
- for (Field declaredField : personClass.getDeclaredFields()) {
- System.out.println(declaredField.getName());
- }
- // 5. getMethods:获取所有public修饰的方法,包含本类以及父类的
- for (Method method : personClass.getMethods()) {
- System.out.println(method.getName());
- }
- // 6. getDeclaredMethods:获取本类中所有方法
- for (Method declaredMethod : personClass.getDeclaredMethods()) {
- System.out.println(declaredMethod.getName());
- }
- // 7. getConstructors:获取所有public修饰的构造器,包含本类的
- for (Constructor<?> constructor : personClass.getConstructors()) {
- System.out.println(constructor.getName());
- }
- // 8. getDeclaredConstructors:获取本类中所有构造器
- for (Constructor<?> declaredConstructor : personClass.getDeclaredConstructors()) {
- System.out.println(declaredConstructor.getName());
- }
- // 9. getPackage:以Package形式返回 包信息
- System.out.println(personClass.getPackage());
- // 10. getSuperClass:以Class形式返回父类信息
- System.out.println(personClass.getSuperclass());
- // 11. getInterfaces:以Class[]形式返回接口信息
- for (Class<?> anInterface : personClass.getInterfaces()) {
- System.out.println(anInterface.getName());
- }
- // 12. getAnnotations:以Annotation[]形式返回注解信息
- for (Annotation annotation : personClass.getAnnotations()) {
- System.out.println(annotation);
- }
-
- }
-
- @Test
- // 第二组:java.lang.reflect.Field类
- public void api_02() throws ClassNotFoundException {
- //得到Class对象
- Class<?> personClass = Class.forName("com.shb.reflection.Person");
- for (Field declaredField : personClass.getDeclaredFields()) {
- // 1. getModifiers:以int形式返回修饰符(有对应的枚举)
- System.out.println(declaredField.getModifiers());
- // 2. getType:以Class形式返回类型
- System.out.println(declaredField.getType());
- // 3. getName:返回属性名
- System.out.println(declaredField.getName());
- }
- }
-
- @Test
- // 第三组:java.lang.reflect.Method类
- public void api_03() throws ClassNotFoundException {
- //得到Class对象
- Class<?> personClass = Class.forName("com.shb.reflection.Person");
- // 6. getDeclaredMethods:获取本类中所有方法
- for (Method declaredMethod : personClass.getDeclaredMethods()) {
- // 1. getModifiers:以int形式返回修饰符
- System.out.println(declaredMethod.getModifiers());
- // 2. getReturnType:以Class形式获取 返回类型
- System.out.println(declaredMethod.getReturnType());
- // 3. getName:返回方法名
- System.out.println(declaredMethod.getName());
- // 4. getParameterTypes:以Class[]返回参数类型数组
- for (Class<?> parameterType : declaredMethod.getParameterTypes()) {
- System.out.println(parameterType.getName());
- }
- }
- }
-
- @Test
- // 第四组:java.lang.reflect.Constructor类
- public void api_04() throws ClassNotFoundException {
- //得到Class对象
- Class<?> personClass = Class.forName("com.shb.reflection.Person");
- // 8. getDeclaredConstructors:获取本类中所有构造器
- for (Constructor<?> declaredConstructor : personClass.getDeclaredConstructors()) {
- // 1. getModifiers:以int形式返回修饰符
- System.out.println(declaredConstructor.getModifiers());
- // 2. getName:返回构造器名(全类名)
- System.out.println(declaredConstructor.getName());
- // 3. getParameterTypes:以Class[]返回参数类型数组
- for (Class<?> parameterType : declaredConstructor.getParameterTypes()) {
- System.out.println(parameterType.getName());
- }
- }
- }
- }
-
- @Deprecated
- class Person implements iA, iB {
- public Person() {
-
- }
-
- public Person(String name, int age, String job, double sar) {
- this.name = name;
- this.age = age;
- this.job = job;
- this.sar = sar;
- }
-
- //属性
- public String name;
- protected int age;
- String job;
- private double sar;
-
- //方法
- public void m1(String A, Integer B) {
-
- }
-
- private void m2() {
-
- }
-
- protected void m3() {
-
- }
-
- void m4() {
-
- }
- }
-
- interface iA {
-
- }
-
- interface iB {
-
- }
- package com.shb.reflection;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * ● 通过反射创建对象
- * 1. 方式一:调用类中的public修饰的无参构造器
- * 2. 方式二:调用类中的指定构造器
- * 3. CLass类相关方法
- * a. newInstance:调用类中的无参构造器,获取对应类的对象
- * b. getConstructor(Class...clazz):根据参数列表,获取对应的public 构造器对象
- * c. getDecalaredConstructor(Class...clazz):根据参数列表,获取对应的构造器对象
- * 4. Constructor类相关方法
- * a. setAccessible:爆破
- * b. newInstance(Object..obj):调用构造器
- */
- public class RelectCreateInstance {
- public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
- //1、获取到User对象
- Class<?> cls = Class.forName("com.shb.reflection.User");
- //2、通过无参构造器创建对象
- Object o = cls.newInstance();
- System.out.println(o);
- //3、通过有参构造器创建对象
- /**
- * public User(String name) {
- * this.name = name;
- * }
- */
- //先得到构造器,在创建实例
- Constructor<?> constructor = cls.getConstructor(String.class);
- Object newInstance = constructor.newInstance("宋海波");
- System.out.println(newInstance);
- //4、通过非public的有参构造器创建对象
- Constructor<?> privateConstructor = cls.getDeclaredConstructor(int.class, String.class);
- //爆破 使用反射可以访问私有的构造器
- privateConstructor.setAccessible(true);
- Object newInstance1 = privateConstructor.newInstance(100, "李四");
- System.out.println(newInstance1);
-
- }
-
- }
-
- class User {
- private int age = 1;
- private String name = "小明";
-
- public User() {
-
- }
-
- public User(String name) {
- this.name = name;
- }
-
- private User(int age, String name) {
- this.age = age;
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
-
- @Override
- public String toString() {
- return "User{" +
- "age=" + age +
- ", name='" + name + '\'' +
- '}';
- }
- }
- package com.shb.reflection;
-
- import java.lang.reflect.Field;
-
- /**
- * 通过反射访问类中的成员
- */
- public class ReflectAccessProperty {
- public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
- //1、得到Student类对象
- Class<?> cls = Class.forName("com.shb.reflection.Student");
- //2、创建对象 o运行类型就是Student
- Object o = cls.newInstance();
- System.out.println(o);
- //3、使用反射操作成员变量 name age
- Field age = cls.getField("age");
- age.set(o, 88);
- System.out.println(o);
- System.out.println(age.get(o));
- //4、使用反射操作name属性 私有的 静态的
- Field name = cls.getDeclaredField("name");
- //因为name是私有的无法设置值,所以对name进行爆破
- name.setAccessible(true);
- name.set(o, "宋海波");
- //应为name是静态的,所以对象写null也是可以的
- name.set(null, "宋海波");
- System.out.println(o);
- //静态的属性name name.get(o) name.get(null) 都可以的
- System.out.println(name.get(o));
- }
- }
-
- class Student {
- private static String name;
- public int age;
-
- public Student() {
- }
-
- @Override
- public String toString() {
- return "Student{" +
- "name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
- }
通过反射访问类中的成员
- package com.shb.reflection;
-
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- /**
- * 通过反射访问类中的成员
- * ● 访问方法
- */
- public class ReflectAccessMethod {
- public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, ClassNotFoundException, InvocationTargetException {
- //1、得到Boss类对应的对象
- Class<?> cls = Class.forName("com.shb.reflection.Boss");
- //2、创建对象
- Object o = cls.newInstance();
- //3、调用public hi方法
- Method hi = cls.getMethod("hi", String.class);
- hi.invoke(o, "晓丽");
- //4、调用private static方法say()
- Method say = cls.getDeclaredMethod("say", int.class, String.class, char.class);
- //应为say方法是私有的所以需要爆破
- say.setAccessible(true);
- Object invoke = say.invoke(o, 100, "张三", '男');
- System.out.println(invoke);
- //因为say方法是static可以传null调用
- say.invoke(null, 100, "张三", '男');
-
- }
- }
-
-
- class Boss {
- private static String name;
- public int age;
-
- public Boss() {
-
- }
-
- private static String say(int n, String s, char c) {
- System.out.println(n + " " + s + " " + c);
- return n + " " + s + " " + c + " 我是return";
- }
-
- public void hi(String s) {
- System.out.println("hi~ " + s);
- }
-
- @Override
- public String toString() {
- return "Boss{" +
- "age=" + age +
- '}';
- }
- }