对反射的理解

346 阅读3分钟

最近在学习AOP的实现,AOP涉及到代理模式,代理模式涉及到反射,刨根掘底那就先看看什么是反射? 印象最最深刻就是在创建JDBC连接的时候,使用Class.forName()通过反射加载数据库的驱动程序;

1、什么是反射?

在运行状态中,对于任意一个类都可以知道该类所以的属性和方法,对于任意一个对象,都能够调用它的任意属性和方法,这种动态获取信息以及调用方法的过程称为Java反射机制;

1、这里就不再详细的描述类加载机制,当我们new Student()的时候,Jvm会将我们编译好的 .class获取到并加载进入内存;

2、将.class文件读入内存中,给student分配对象的内存空间,同时产生唯一一个改类的Class类对象,该Class类对象记录了student的信息;
所谓反射就是指:我们通过Class对象获取到Student对象的信息;

实际上在Java中每个类都有一个Class对象,每当我们编写并且编译一个新创建的类就会产生一个对应Class对象并且这个Class对象会被保存在同名.class文件里(编译后的字节码文件保存的就是Class对象),那为什么需要这样一个Class对象呢?当我们new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载器子系统会将对应Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要实例对象或者提供静态变量的引用值。需要特别注意的是,手动编写的每个class类,无论创建多少个实例对象,在JVM中都只有一个Class对象,即在内存中每个类有且只有一个相对应的Class对象;

总结:由上我们了解了反射的定义,以及每个类在内存中 存在 有且只有一Class对象;

2、如何获得Class对象?(code在下面)

2.1、使用老祖宗(Object类)提供的getClass()方法;
2.2、通过类的静态class属性获得Class对象;
2.3、通过Class类的静态方法Class.forName()获得;

3、下面我们看看Class类中提供了哪些方法获取所需对象的信息?(code在下面)

Class中提供的方法比较多,在此就不做详细的讲解,建议不要死记硬背方法,需要使用时去寻找就可以了,一般在源码上面都会解释方法的作用是什么;

public class StudentTest {
    public static void main(String[] args) throws ClassNotFoundException {

        Student student = new Student();

        //Object的getClass()方法
        Class<? extends Student> objectGetClass = student.getClass();

        //通过类的静态class属性获得Class对象
        Class<Student> studentClass = Student.class;

        //通过Class类的静态方法Class.forName()获得
        Class<?> studentClassForName = Class.forName("com.reflect.Student");

        //查看HashCode
        System.out.println(String.format("objectGetClass的hashCode码[%s],studentClass的hashCode码[%s],studentClassForName的hashCode码[%s]",
                objectGetClass.hashCode(),studentClass.hashCode(),studentClassForName.hashCode()));

        //判断是否是同一个对象 true
        System.out.println("studentClassForName == studentClass" + (studentClassForName == studentClass));

        //获取全路径类名  com.reflect.Student
        System.out.println(studentClassForName.getName());

        //类名   Student
        System.out.println(studentClassForName.getSimpleName());

        //获取类修饰符,返回int  Modifier类中提供方法判断
        System.out.println(studentClassForName.getModifiers());
        //判断是否为公共的
        System.out.println(Modifier.isPublic(studentClassForName.getModifiers()));

        //获得父类  Object
        System.out.println(studentClassForName.getSuperclass());

        //获取实现的接口,接口可以实现多个,所以返回数组
        System.out.println(studentClassForName.getInterfaces().length);

        //获取公有字段
        Field[] fields = studentClassForName.getFields();

        //获取所有字段
        Field[] declaredFields = studentClassForName.getDeclaredFields();
        for(Field f : declaredFields){
            System.out.println(f.getName());
        }
    }
}

总结:通过以上描述与Code应该对反射有了大致了解,如果想印象更深刻,建议去了解下类加载机制,当然,在后文中我也会描述自己对类加载机制的理解;

鄙人不才,在您面前献丑只愿与您结伴而行,文章若有不当之处,望大佬指点一二;如果我对您有帮助的话,还希望您能点赞分享,成长是一场苦涩的独自修行,我很需要您的陪伴与支持,这也是鄙人不断前行的根本动力,让我们在互相陪伴见证彼此生长的同时能够感染身边最亲近的人一同成长,鄙人在此叩谢!