Java基础之反射

107 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

1.1 反射概述

在这里插入图片描述

  • Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展

1.2 反射获取Class类的对象

  • 我们要想通过反射去使用一个类,==首先我们要获取到该类的字节码文件对象==,也就是类型为Class类型的对象这里我们提供三种方式获取Cass类型的对象
    • 1、使用类的class属性来获取该类对应的Class对象。举例: Student.class将会返回Student类对应的Class对象

    • 2、调用对象的getClass()方法, 返回该对象所属类对应的Class对象 该方法是Object类中的方法,所有的Java对象都可以调用该方法

    • 3、使用Class类中的静态方法forName(StringclassName), 该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径

package test;

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException {
        //1、使用类的class属性来获取该类对应的Class对象
        Class<Student> c1 = Student.class;
        System.out.println(c1); //class test.Student

        Class<Student> c2 = Student.class;
        System.out.println(c1 == c2); //true;一个类只有一个字节码文件对象

        //2、调用对象的getClass()方法, 返回该对象所属类对应的Class对象
        Student s = new Student();
        Class<? extends Student> c3 = s.getClass();
        System.out.println(c1 == c3); //true

        //3、使用Class类中的静态方法forName(StringclassName)
        Class<?> c4 = Class.forName("test.Student");
        System.out.println(c1 == c4); //true
    }
}

1.3 反射获取构造方法并使用

  • Class类中用于获取构造方法的方法
方法名说明
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?> [] getDeclaredConstructors [dɪˈkleəd]返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>...parameterTypes)返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?> ...parameterTypes)返回单个构造方法对象
  • Constructor类中用来创建对象的方法
方法名说明
T newInstance(Object...initargs)根据指定的构造方法创建对象
package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("test.Student");

        //1,Constructor<?>[] getConstructors() 	返回所有公共构造方法对象的数组
        Constructor<?>[] cons1 = c.getConstructors();
        for(Constructor con:cons1) {
            System.out.println(con);
//            public test.Student(java.lang.String,int,java.lang.String)
//            public test.Student()
        }
        System.out.println("--------");

        //2,Constructor<?> [] getDeclaredConstructors 	返回所有构造方法对象的数组
        Constructor<?>[] cons2 = c.getDeclaredConstructors();
        for(Constructor con:cons2) {
            System.out.println(con);
//            public test.Student(java.lang.String,int,java.lang.String)
//            test.Student(java.lang.String,int)
//            private test.Student(java.lang.String)
//            public test.Student()
        }
        System.out.println("--------");

        /*
        一、首先把这个类的带包的字符串路径传给forName()方法得到字节码文件Class对象c
        二、c调用getConstructors()得到单个的构造方法对象con1
        三、通过con1调用newInstance()创建一个对象,这就叫反射*/

        //3,Constructor<T> getConstructor(Class<?>...parameterTypes) 	返回单个公共构造方法对象
        //参数是:你要获得的构造方法的参数个数和数据类型对应字节码文件
        Constructor<?> con1 = c.getConstructor();

        //Constructor提供了一个类的单个构造方法信息和访问权限
        //5,T newInstance(Object…initargs) 	根据指定的构造方法创建对象
        Object obj1 = con1.newInstance();
        System.out.println(obj1); //Student{name='null', age=0, address='null'}
    }
}

1.4 反射获取成员变量并使用

  • Class类中用于获取成员变量的方法
方法名说明
Field[ ] getFields()返回所有公共成员变量对象的数组
Field[ ] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象
  • Field类中用于给成员变量赋值的方法
方法名说明
void set(Object obj, Object value)给obj对象的成员变量赋值为value
package test;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //获取Class对象
        Class<?> c = Class.forName("test.Student");

        //1,Field[] getFields() 	返回所有公共成员变量对象的数组
        Field[] fields1 = c.getFields();
        for(Field field:fields1) {
            System.out.println(field);
            //public java.lang.String test.Student.address
        }
        System.out.println("--------");

        //2,Field[ ] getDeclaredFields() 	返回所有成员变量对象的数组
        Field[] fields2 = c.getDeclaredFields();
        for(Field field:fields2) {
            System.out.println(field);
//            private java.lang.String test.Student.name
//            int test.Student.age
//            public java.lang.String test.Student.address
        }
        System.out.println("--------");

        /* 
         一、首先把这个类的带包的字符串路径传给forName()方法得到字节码文件Class对象c
         二、通过c调用getField()得到成员变量对象addressField
         三、addressField调用set()方法给obj对象的address赋值*/
        
        //3,Field getField(String name) 	返回单个公共成员变量对象
        Field addressField = c.getField("address");
        System.out.println(addressField);
        //public java.lang.String test.Student.address
        
        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
        //5,void set(Object obj, Object value) 	给obj对象的成员变量赋值为value
        addressField.set(obj,"成都"); //给obj的成员变量addressField》address赋值为成都
        System.out.println(obj); //Student{name='null', age=0, address='成都'}
    }
}

1.5 反射获取成员方法并使用

  • Class类中获取成员方法的方法
方法名说明
Method[ ] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[ ] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?> .. parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?> .. parameterTypes)返回单个成员方法对象
  • Method类中用于调用成员方法的方法
方法名说明
Object invoke(Object obj, Objet... args)调用obj对象的成员方法,参数是args,返回值是Object类型
package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("test.Student");

        //1,Method[ ] getMethods() 	返回所有公共成员方法对象的数组,包括继承的
        Method[] methods1 = c.getMethods();
        for(Method method:methods1) {
            System.out.println(method);
//            public java.lang.String test.Student.toString()
//            public void test.Student.method1()
//            public void test.Student.method3()
//            public void test.Student.method2()
//            public final void java.lang.Object.wait() throws java.lang.InterruptedException
//            public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
//            ...
        }
        System.out.println("---------");

        //2,Method[ ] getDeclaredMethods() 	返回所有成员方法对象的数组,不包括继承的
        Method[] methods2 = c.getDeclaredMethods();
        for(Method method:methods2) {
            System.out.println(method);
//            public java.lang.String test.Student.toString()
//            private void test.Student.function()
//            public void test.Student.method1()
//            public void test.Student.method3()
//            public void test.Student.method2()
        }

        //3,Method getMethod(String name, Class<?> … parameterTypes) 	返回单个公共成员方法对象
        Method m = c.getMethod("method1");

        //获取无参构造方法并创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

        //5,Object invoke(Object obj, Objet… args) 	调用obj对象的成员方法,参数是args,返回值是Object类型
        //第一个Object:返回值类型;obj:对象;args:方法需要的参数
        m.invoke(obj); //method1
    }
}