Java 反射

Posted Shen_JC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 反射相关的知识,希望对你有一定的参考价值。

看了很多关于反射的文章和例子,却从没有自己好好总结总结。Let’s do it。

反射相关的类和方法

java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;

获取Class的三种方式

    /**
     * 获取Class的三种方式
     */
    public static void testGetClass() 

        Class<?> c1 = null;
        Class<?> c2 = null;
        Class<?> c3 = null;

        try 
            // 第一种方式
            c1 = Class.forName("com.example.java.Employee");
         catch (ClassNotFoundException e) 
            System.out.println("没有找到Employee类!");
            e.printStackTrace();
        
        // 第二种方式
        c2 = Employee.class;

        // 第三种方式
        Employee employee = new Employee();
        c3 = employee.getClass();

        System.out.println("类名称, Name:" + c1.getName() + " , SimpleName:" + c1.getSimpleName());
        System.out.println("类名称, Name:" + c2.getName() + " , SimpleName:" + c2.getSimpleName());
        System.out.println("类名称, Name:" + c3.getName() + " , SimpleName:" + c3.getSimpleName());

运行结果:

类名称, Name:com.example.java.Employee , SimpleName:Employee
类名称, Name:com.example.java.Employee , SimpleName:Employee
类名称, Name:com.example.java.Employee , SimpleName:Employee

通过Class来创建对象

  public static void newInstanceFromClass() 

        Class<?> c = null;

        try 
            c = Class.forName("com.example.java.Employee");
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        

        try 
            // Class.newInstance()方法会调用类的无参构造函数,所以类一定要有无参构造函数,要不然有出错。
            Employee employee = (Employee) c.newInstance();
            employee.setName("LiLei");
            employee.setAge(20);
            System.out.println(employee);
         catch (InstantiationException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
        

    

【运行结果】

[ Name:LiLei, mAddress:null, mAge:20, mPhoneNumber:null ]

通过Class获取并使用类的构造函数

    /**
     * 通过Class获取类的构造函数,包含修饰符、名字、参数类型
     */
    public static void testGetConstructors() 
        Class<?> c = null;

        try 
            c = Class.forName("com.example.java.Employee");
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        

        Employee employee1 = null;
        Employee employee2 = null;

        // 获取所有的构造函数
        Constructor<?> constructors[] = c.getConstructors();
        StringBuilder sb = new StringBuilder();

        for (Constructor constructor : constructors) 
            //获得构造函数的修饰符,例如public,static等等
            sb.append(Modifier.toString(constructor.getModifiers()) + " ");
            // 获取构造函数的名字
            sb.append(constructor.getName());
            // 获取构造函数中的参数,如果没有参数,则返回length为0的数组。
            Class[] types = constructor.getParameterTypes();
            sb.append(" ( ");
            for (Class type : types)
                sb.append(type.getSimpleName()); // 获取参数的类型名字
                sb.append(" ");
            
            sb.append(" ) ");
            sb.append("\\r\\n");
        

        System.out.println(sb.toString());

        // 调用构造行数来初始化对象
        try 
            employee1 = (Employee) constructors[0].newInstance("Lucy", "USA", 29, "1892222222");
            employee2 = (Employee) constructors[1].newInstance();
            employee2.setName("Jack");
         catch (InstantiationException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
         catch (InvocationTargetException e) 
            e.printStackTrace();
        

        System.out.println(employee1);
        System.out.println(employee2);
    

通过Class获取类实现的接口


    /**
     * 通过Class获取类实现的接口
     */
    public static void testGetInterfaces() 
        Class<?> c = null;

        try 
            c = Class.forName("com.example.java.Employee");
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        

        // 获取实现的接口
        Class[] interfaces = c.getInterfaces();
        StringBuilder sb = new StringBuilder();
        sb.append("实现的接口有: ");
        for (Class i :interfaces) 
            sb.append(i.getName());
            sb.append(" ");
        

        System.out.println(sb);
    

通过Class获取类继承的父类

    /**
     * 通过Class获取类继承的父类
     */
    public static void testGetSuperclass() 
        Class<?> c = null;

        try 
            c = Class.forName("com.example.java.Engineer");
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        
        // 获取父类
        Class<?> parent = c.getSuperclass();
        System.out.println("继承的父类:" + parent.getName());

    

通过Class获取类的属性变量

   /**
     * 通过Class获取类的属性变量
     */
    public static void testGetFields() 
        Class<?> c = null;

        try 
            c = Class.forName("com.example.java.Engineer");
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        
        StringBuilder sb = new StringBuilder();

        // getFields() 返回本类或者本接口中的属性字段,不包含父类或者接口中的。
        Field[] fields = c.getDeclaredFields();

        sb.append("本类或本接口的属性字段:\\n");
        for (Field field : fields) 
            // 属性字段的修饰符
            sb.append(Modifier.toString(field.getModifiers()) + " ");
            // 属性字段的类型
            sb.append(field.getType().getSimpleName() + " ");
            // 属性字段的名字
            sb.append(field.getName());
            sb.append("\\n");
        

        // getFields() 返回可以访问的public的属性字段,包括本类和来自父类或者接口中的public的。
        fields = c.getFields();
        sb.append("public的属性字段:\\n");
        for (Field field : fields) 
            sb.append(Modifier.toString(field.getModifiers()) + " ");
            sb.append(field.getType().getSimpleName() + " ");
            sb.append(field.getName());
            sb.append("\\n");
        

        try 
            Field field = c.getDeclaredField("isJunior");
            sb.append(field.getName());
         catch (NoSuchFieldException e) 
            e.printStackTrace();
        

        System.out.println(sb);
    

通过Class获取类的方法

  public static void testGetMethods() 

        Class<?> c = null;

        try 
            c = Class.forName("com.example.java.Engineer");
         catch (ClassNotFoundException e) 
            e.printStackTrace();
        

        StringBuilder sb = new StringBuilder();

        sb.append("本类或本接口的方法:\\n");
        Method[] declaredMethods = c.getDeclaredMethods();
        for (Method method : declaredMethods) 
            // 方法修饰符
            sb.append(Modifier.toString(method.getModifiers()) + " ");
            // 方法返回类型
            sb.append(method.getReturnType().getName() + " ");
            // 方法名字
            sb.append(method.getName() + " ");
            sb.append("(");
            // 获取方法的所有参数
            for (Class type : method.getParameterTypes()) 
                sb.append(type.getName());
                sb.append(" ");
            

            sb.append(") \\n");
        

        sb.append("所有public的方法:\\n");
        // 返回可以访问的public的方法,包括本类和来自父类或者接口中的public的。
        Method[] methods = c.getMethods();
        for (Method method : methods) 
            sb.append(Modifier.toString(method.getModifiers()) + " ");
            sb.append(method.getReturnType().getName() + " ");
            sb.append(method.getName() + " ");
            sb.append("(");

            for (Class type : method.getParameterTypes()) 
                sb.append(type.getName());
                sb.append(" ");
            

            sb.append(")");

            // 获取方法会抛出的Exception的异常类型
            Class[] exceptionTypes = method.getExceptionTypes();

            if (exceptionTypes.length > 0) 
                sb.append(" throws ");
                for (Class type : exceptionTypes) 
                    sb.append(type.getName());
                    sb.append(" ");
                
            

            sb.append("\\n");
        

        System.out.println(sb);
    

通过Class修改类的变量


    /**
     * 通过Class修改类的变量
     */
    public static void testModifyFiled() 

        Class<?> c = null;
        Object object = null;

        try 
            c = Class.forName("com.example.java.Engineer");
            object = c.newInstance();
         catch (ClassNotFoundException e) 
            e.printStackTrace();
         catch (InstantiationException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
        

        try 
            Field field1 = c.getDeclaredField("isJunior");
            Field field2 = c.getField("mNickName");
            field1.setBoolean(object, true); // 修改属性变量
            field2.set(object, "NICE");      // 修改属性变量

            System.out.println(field1.getBoolean(object) + " " + field2.get(object));
         catch (NoSuchFieldException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
        

        System.out.println(object.toString());
    

通过Class来调用类的方法

   /**
     * 通过Class来调用类的方法
     */
   public static void testCallMethod() 

        Class<?> c = null;
        Object object = null;

        try 
            c = Class.forName("com.example.java.Engineer");
            object = c.newInstance();
         catch (ClassNotFoundException e) 
            e.printStackTrace();
         catch (InstantiationException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
        

        try 
            Method method1 = c.getDeclaredMethod("setmLevel", int.class); // 获取本类中“setmLevel”的方法
            method1.invoke(object, 4); // 调用“setmLevel”方法

            Method method2 = c.getMethod("setName", String.class); // 获取父类中public的“setName”的方法
            method2.invoke(object, "Jonson");  // 调用“setName”方法

         catch (NoSuchMethodException e) 
            e.printStackTrace();
         catch (InvocationTargetException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
        

        System.out.println(object.toString());
    

以上是关于Java 反射的主要内容,如果未能解决你的问题,请参考以下文章

JAVA反射Field

反射机制在java中如何做呀?

如何利用java的反射机制动态创建对象

说说对java反射的理解,使用反射如何获取一个类的所有方法,使用反射需要注意哪些问题?

请问java中的反射机制与用法

Java反射机制