JavaSE 学习基础之反射小结(待写...)

分享 谭海棠 ⋅ 于 2020-06-26 19:04:11 ⋅ 最后回复由 青牛 2020-06-26 23:09:55 ⋅ 67 阅读

为了明白为啥有反射这个东西,得先从JVM如何获取.class文件开始!

类的加载三步骤:

  • 1、加载:从硬盘或网络中读取一个.class文件数据到JVM内存中
  • 2、连接三小步:
    • 1)校验:其中一项看字节码的数据是否以“魔数cafe”以及当前的JVM运行的JDK版本是否可以运行该字节码的数据。例如:JDK1.8可以运行用JDK1.7编译的字节码,反过来就不可以
    • 2)准备:给成员变量(类变量/静态变量)赋默认值;把常量(final)等值在方法去的常量池中准备好
    • 3)解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程,可以理解为把类中的对应的类型名换成该类型的Class对象的地址
  • 3、初始化类初始化,类初始化由两部分组成
    • 1)静态变量的显示初始化代码,赋值代码
    • 2)静态代码块
    • 3)注:1)和2)的顺序是从上往下
      不说了,我要甩图啦!来了老弟,类加载与初始化↓
      file

      注意事项

  • 1、当一个类初始化时,发现它的父类如果没有初始化,会先初始化父类
  • 2、每一个类只会初始化一次,并且类初始化的过程是线程安全的
  • 3、哪些操作导致类的初始化?这句话的意思:类的加载不一定就会发生类初始化(可能只会发生加载和连接这两步)
    • 1)main方法所在的类在加载时,直接就先初始化
    • 2)new一个类的对象,一定会先完成类的初始化
    • 3)调用该类的静态变量(final的常量除外)和静态方法
    • 4)使用java.lang.reflect包的方法对类进行反射调用
    • 5)当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类
  • 4、哪些情况不会导致类初始化?
    • 1)引用静态常量(final)不会触发此类的初始化(因为常量在连接-准备的时候就已经在常量池中了)
    • 2)当访问一个静态域时,只有真正声明这个域的类才会被初始化,换句话来说:通过子类访问父类的静态域时,只会初始化父类,不会初始化子类
    • 3)通过数组定义类引用,不会触发此类的初始化,如:Student[] stus = new Student[3];时Student类并不会被初始化(因为Student[]是一个数组类型并不是一个Student类型,只有它的元素才是Student类型)
  • 5、那我们现在都知道了类的加载有三步骤生成对应的Class对象:加载、连接、类初始化。那new一个实例对象时会执行实例初始化,也有三步骤:
    • 1)非静态域的显示赋值
    • 2)非静态代码块的执行
    • 3)构造器的执行
    • 4)其中1)和2)是按顺序执行的,3)一定是最后才被执行!
    • 5)记得不要把类初始化和实例初始化弄混,不行倒回去再瞪瞪emmm
  • 6、注:JVM这样做的目的就是为了尽可能的做到“懒”加载,需要用才载入内存,不需要的不载!

    类加载的结果

  • 结论:无论如何操作,最终类加载的结果都是为了:在方法区中有一个唯一的Class对象来代表一个类型,每一种类型都有且只有一个Class对象
  • 1、java.lang.Class
    • 1)Class类的实例表示正在运行的Java引用程序中的类和接口
    • 2)枚举是一种类,注释(注解)是一种接口
    • 3)每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维度的数组都共享该Class对象。也就是说数组也有对应的Class对象
    • 4)八大基本类型和关键字void也有对应的Class对象
  • 2、如何在程序中获取对应的Class对象
    • 1)类型名.class (注:八大基本类型和void,只能通过这种方式)
    • 2)实例对象.getClass()(注:只能用于引用数据类型)
  • 3、Class.forName("完全限定名称")(注:数组也可以通过该方式得到对应的Class对象)
  • 4、类加载器对象.loadClass("完全限定名称")

    四种类加载器

  • 1、引导类加载器(Bootstrap Classloader):又称为根类加载器
    • 1)它负责加载Java的核心库(JAVA_HOME/jre/lib/rt.jar等或sun.boot.class.path路径下的内容),是用原生代码(C/C++)来实现的,并不继承自java.lang.ClassLoader,所以通过Java代码获取引导类加载器对象将会得到null
  • 2、扩展类加载器(Extension ClassLoader)
    • 1)它由sun.misc.Launcher$ExtClassLoader实现,是java.lang.ClassLoader的子类,负责加载Java的扩展库(JAVA_HOME/jre/lib/ext/*.jar或java.ext.dirs路径下的内容)
  • 3、应用程序类加载器(Application Classloader)
    • 1)它是由sun.misc.Launcher$AppClassLoader实现,是java.lang.ClassLoader的子类,负责加载Java应用程序类路径(classpath、java.class.path)下的内容
  • 4、自定义类加载器
    • 1)开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需要,例如对字节码进行加密来避免class文件被反编译,或者加载特殊目录下的字节码数据
    • 2)例如:tomacat加载特定目录下的类
  • 注:Java的类加载过程是一个双亲(parent)委托模式加载的,4,3,2,1加载器是组合关系,如4认3为parent加载器,但不是继承关系。例如:当“应用程序类加载器”接到一个加载任务时:
    • 1)先搜索内存中是否已经加载过了,如果加载过了,就可以找到对应的Class对象,那么就不加载了
    • 2)如果没有找到,把这个任务先提交给“parent”,“父”加载器接到任务时,也是重复1)和2)操作
    • 3)直到传给了根加载器,如果根加载器可以加载,就完成了,如果不能加载,往回传,依次每个加载器尝试在自己负责的路径下搜索,如果找到就直接返回Class对象,如果一直回传到“应用程序类加载器”,还是没有找到,就会报ClassNotFoundException
      别说了,先上一波图,有点脑路↓
      file
  • 再注:为啥要怎么干,传来传去的emmm
    • 1)目的是为了安全,防止你写一个和核心类库一样的类,每一个加载器负责自己的路径下的东西!

      类加载器的作用

  • 1、最主要的作用就是用来加载类的
  • 2、还可以起到辅助的作用:可以用类加载器来加载“类路径下”的资源文件,如在JavaSE阶段的:src下的文件-->bin目录下
  • 3、ClassLoader
    • 1)静态方法,ClassLoader.getSystemResourceAsStream("文件名");但是这个只适用于JavaSE阶段,因为它用应用程序类加载器去加载的,注:在Web阶段用这个方法是有问题的,因为Web阶段的类路径在WEB-INF/classes下,必须由Web自定义的类加载器去加载
    • 2)非静态方法,类加载器对象.getResourceAsStream("文件名");该方法适用于Web阶段!

      好了,来啦!反射

      别说了,上来先来一段定义,反射:在运行时可以获取到类的信息,对类进行操作,而且该类可能是在编译时完全未知的类型。反射使得Java具有动态语言的特征,注:我们在正常的操作是 从类->对象(new);现在有了反射就是从 该类的Class对象->操作类的所有成员!
  • 类==》对象:先写类==》用类创建对象->通过对象操作部分公开成员
  • 提前笔记:反射又很多种,例如:tomcat,hibernate,spring,mybatis等各种框架都运用了反射机制(也不是很明白,可能学到了才懂吧!emmm)。
  • 反射在开发的应用有如下几个方面
    • 1)在运行期间,动态的获取某个类的详细信息
    • 2)在运行期间,动态的创建任意类型的对象,只要这个类可以创建对象
    • 3) 在运行期间,动态的为对象的属性赋值
    • 4) 在运行期间,动态的调用任意对象的任意方法
    • 5)在运行期间,动态获取注解的信息(Web框架经常使用!)
  • 反射创建对象两种方式
    • 1)Class对象.newInstance();注:只支持有无参构造的
    • 2)通过Class对象获取到该类的构造器,然后 获取的构造器对象.newInstance(Ojbect ... initargs);注:都支持!

      不写了,脑壳疼(不抄了emmm)

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海牛部落-谭海棠,http://hainiubl.com/topics/75159
回复数量: 1
  • 青牛 国内首批大数据从业者,就职于金山,担任大数据团队核心研发工程师
    2020-06-26 23:09:55

    看样子你还没有写完,加油

暂无评论~~
  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
Ctrl+Enter