java反射学习小结

1.1类加载【理解】

- 类加载的描述
  - 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或者类初始化
- 类的加载
  - 就是指将class文件读入内存,并为之创建一个 java.lang.Class 对象
  - 任何类被使用时,系统都会为之建立一个 java.lang.Class 对象
- 类的连接
  - 验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
  - 准备阶段:负责为类的类变量分配内存,并设置默认初始化值
  - 解析阶段:将类的二进制数据中的符号引用替换为直接引用
- 类的初始化
  - 在该阶段,主要就是对类变量进行初始化
- 类的初始化步骤
  - 假如类还未被加载和连接,则程序先加载并连接该类
  - 假如该类的直接父类还未被初始化,则先初始化其直接父类
  - 假如类中有初始化语句,则系统依次执行这些初始化语句
  - 注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3
- 类的初始化时机
  - 创建类的实例
  - 调用类的类方法
  - 访问类或者接口的类变量,或者为该类变量赋值
  - 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
  - 初始化某个类的子类
  - 直接使用java.exe命令来运行某个主类

1.2

类的加载过程:
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾),接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类就称为运行时类,此运行时类,就作为Class的一个实例。
换句话说,Class的实例就对应着一个运行时类。
加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
哪些类型可以有class对象?

class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
interface:接口
[]:数组
enum:枚举
annotation:注解@interface
primitive Type:基本数据类型
void
package reflect;

2.1反射的概述【理解】

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

2.2获取Class类对象的三种方式【应用】

2.2.1三种方式分类

  • 类名.class属性

  • 对象名.getClass()方法

  • Class.forName(全类名)方法

public class test01 {


    //前三种方式掌握,最后一种了解,用的不多,方式三用的比较多,更能够体现动态性,编译时先不去确定
    @Test
    public void test1() throws ClassNotFoundException {
        //方式一:调用运行时类的属性.class
        Class clazz = Person.class;//Class带泛型,因为是Person给它赋的值,所以具体操作的是Person
        System.out.println(clazz);//class test.Person,不加泛型不会影响输出的效果,加上泛型可以避免后面的操作进行强转

        //方式二:通过运行时类的对象,调用getClass方法
        Person p1=new Person();
        Class clazz2 = p1.getClass();//得到这个对象是哪个类造的,此方法在Object类中进行声明,得到它所属的类本身,再赋给Class
        System.out.println(clazz2);//class test.Person

        //方式三:调用Class的静态方法:forName(String classPath)
        //不要写成Class.forName("Person");因为同一个module不同的包下可能都有Person,要说清楚是哪个包下的Person

        Class clazz3 = Class.forName("test.Person");//包含包名在内的类的全名,test是包名
        System.out.println(clazz3);//class test.Person
       // clazz3=Class.forName("java.lang.String");//自己定义的类和API定义的类都可以作为Class的实例
       // System.out.println(clazz3);//class java.lang.String

        System.out.println(clazz==clazz2);//true
        System.out.println(clazz==clazz3);//true

        //虽然方式不同,但获取的是内存中的同一个运行时类

        //方式四:使用类的加载器:ClassLoader
        //因为这个测试方法是写在test01这个类中的
        ClassLoader classLoader = test01.class.getClassLoader();

        //得到之后,显式地load class,即显式的去加载某一个类
        Class clazz4 = classLoader.loadClass("test.Person");
        System.out.println(clazz4);//class test.Person
        System.out.println(clazz==clazz4);//true

    }
//注意:如果Person类是写在当前module的src下面,直接"Person"即可,不要写成"src.Person"或者"src\\Person"

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值