zoukankan      html  css  js  c++  java
  • Java基础:反射学习笔记

    反射

    类的加载

    当程序主动使用某个类时,如果该类还没有被加载到内存中,则系统会通过加载、连接、初始化这三个步骤对该类进行初始化。有时会把这一整个流程统称为类加载或类初始化。类加载指的是将类的class文件读入内存中,并为之创建一个 java.lang.Class对象,也就是说程序使用任何类的时候,都会为其创建一个class对象。

    类的连接

    类被加载之后,系统会为之生成一个Class对象,接着会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中。类的连接又分为下面三个阶段:

    验证:确保被加载类的正确性

    准备:负责为类的静态成员分配内存,并设置默认初始化值

    解析:将类中的符号引用替换为直接引用

    类的初始化

    初始化阶段的重要工作是执行类的初始化方法,方法是由编译器自动生成,主要是对静态Field进行初始化(赋值和静态代码块)。

    JVM初始化一个类包含如下几个步骤:

    1. 假如这个类还没有被加载和连接,则程序先加载并连接该类。
    2. 假如该类的父类还没有被初始化,则先初始化其父类。
    3. 假如类中有初始化语句(静态),则系统依次执行这些初始化语句。

    由第二条可以推出,JVM最先初始化的总是java.lang.Object类。

    注意:

    1. 调用类中的final常量(值在编译时可以确定),不会引起该类初始化(即使是static),因为它在编译其实是连接阶段被赋值,会被当成“宏变量”处理,使用常量时,常量会被不加思考替换成赋的值,所以无需初始化类。就是说在A类中 static final String a = "hello"; 则A.a不引起初始化,而当static final String a = System.currentTimeMills() + ""; (编译时确定不了),则A.a会引起A类的初始化。
    2. 当使用ClassLoader的loadClass()方法来加载某个类时,该方法只是加载该类,应不会执行类的初始化
    3. 使用Class的forName()静态方法才会导致强制初始化该类。
    4. clinit方法只会执行一次

    类加载器

    类加载器

    类加载器负责将.class文件加载到内存中,并为之生成对应的Class对象。类加载器负责加载所有的类,系统为所有加载到内存中的类生成一个java.lang.Class 的实例。

    类加载器的组成:Bootstrap ClassLoader 根类加载器 : 也被称为引导类加载器,负责Java核心类的加载,比如System类,在JDK中JRE的lib目录下rt.jar文件中的类Extension ClassLoader 扩展类加载器 : 负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录System ClassLoader 系统类加载器 : 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径,主要是我们开发者自己写的类

    反射

    Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等。

    Class对象

    Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件。当程序主动去使用某个类时,JVM会通过前面提到的三个步骤:加载、连接和初始化三个步骤对类进行初始化。被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是java.lang.Class。这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类。Class类的概念尽管很抽象,但是无疑,它是反射机制的起源,是Java语言中一个精巧美妙地设计。下面是翻译后的中文文档的描述:Class类的实例表示正在运行的Java应用程序的类和接口。枚举是一种类,注释(注解)是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的Java类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。Class没有公用构造方法。Class对象是在加载类时由JVM以及通过调用类加载器中的defineClass方法自动构造的。

    Java反射机制的类库支持

    在深入到反射机制之前,先探析一下反射机制的定义和应用。反射机制定义:Java反射机制是在运行状态时,对于任意一个类,都能够直到这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。在Java中,Class类和java.lang.reflect类库一起构成了对Java反射机制的支持。其中最常使用到的类是ConstructorFieldMethod,而这三个类都继承了一个接口java.lang.reflect.Member

    反射的基本实现

    实验类

    /**
     * 实验类
     */
    public class Cat {
        private String name = "";private String master = "";
        private int age = 0;
        public Cat(){
            
        }
        private Cat(String name, String master){
            
        }
        public Cat(String name, String master, int age){
            
        }
        public void eat(){
            System.out.println("小鱼干真好吃~"); 
        }
        private void play(){ 
            System.out.println("快来陪我玩~"); 
        }
        @Override
        public String toString(){
            return"Cat [name=" + name + ", master=" + master + ", age=" + age + "]"; 
        }
    }
    

    获取Class对象的三种方法

    1. 通过类名获取:Class c1 = Student.class; 调用某各类的class属性来获取Class对象。
    2. 通过对象获取:Class c2 = stu.getClass(); 通过getClass方法,该方法是Object类下的一个方法。
    3. 通过全类名获取:Class c3 = Class.forName("全限定类名"); 会有一个ClassNotFoundException异常
    public class ReflectDemo01 {
        public static void main(String[] args) throws Exception{
            Cat c = new Cat(); Class cat1 = Class.forName("algorithms.sort.Cat");
            Class cat2 = Cat.class; Class cat3 = c.getClass(); System.out.print(cat1 == cat2);
            System.out.print(cat2 == cat3);
        }
    }//输出结果truetrue
    

    获取构造器

    public class ReflectDemo02 {
        public static void main(String[] args) throws Exception{
            Class cat = Cat.class;
            //获取所有公共构造方法
            Constructor cons[] = cat.getConstructors();
            for (Constructor con : cons) {
                System.out.println("getConstructors-----------" + con);
            }
            System.out.println("**************************************");
            //获取所有构造方法
            Constructor<?> cons2[] = cat.getDeclaredConstructors();
            for (Constructor<?> con2 : cons2) {
                System.out.println("getDeclaredConstructors---" + con2);
            }
        }
    }/*输出结果
    getConstructors-----------public algorithms.sort.Cat(java.lang.String,java.lang.String,int)
    getConstructors-----------public algorithms.sort.Cat()
    **************************************
    getDeclaredConstructors---public algorithms.sort.Cat(java.lang.String,java.lang.String,int)
    getDeclaredConstructors---private algorithms.sort.Cat(java.lang.String,java.lang.String)
    getDeclaredConstructors---public algorithms.sort.Cat()*/
    
    

    获取成员变量

    public class ReflectDemo03 {
        public static void main(String[] args) throws Exception{
            Class cat = Cat.class;
            //获取构造器
            Constructor<?> cons = cat.getConstructor(String.class,String.class,int.class);
            //实例化对象
            Cat cat1 = (Cat)cons.newInstance("tom","denny",5);
            System.out.println(cat1);
            System.out.println("****************");
            Field fields = cat.getDeclaredField("name");
            //打开访问权限限制
            fields.setAccessible(true); fields.set(cat1, "jack");
            System.out.println(cat1);
        }
    }/*输出结果
    Cat [name=tom, master=denny, age=5]
    ****************
    Cat [name=jack, master=denny, age=5]*/
    

    获取成员方法

    public class ReflectDemo04 {
        public static void main(String[] args) throws Exception{
            Class cat = Cat.class;
            //获取构造器
            Constructor<?> cons = cat.getConstructor(String.class, String.class, int.class);
            //实例化对象
            Cat cat1 = (Cat) cons.newInstance("tom", "denny", 5);
            System.out.println(cat1); System.out.println("****************");
            //获取私有和公共成员方法
            Method method1 = cat.getDeclaredMethod("setName", String.class);
            Method method2 = cat.getDeclaredMethod("eat"); method1.setAccessible(true);
            method1.invoke(cat1, "petter");
            System.out.println(cat1);
            method2.invoke(cat1);
        }
    }/*输出结果
    Cat [name=tom, master=denny, age=5]
    ****************
    Cat [name=petter, master=denny, age=5]小鱼干真好吃~*/
    

  • 相关阅读:
    PAT 甲级 1115 Counting Nodes in a BST (30 分)
    PAT 甲级 1114 Family Property (25 分)
    PAT 甲级 1114 Family Property (25 分)
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
  • 原文地址:https://www.cnblogs.com/jinjun99/p/13515815.html
Copyright © 2011-2022 走看看