类加载机制与反射

1. JVM和类

当运行一个Java程序时,该命令会启动一个Java虚拟机进程,同一个JVM的所有线程、所有变量都处于同一个进程里,他们都使用该JVM进程的内存区。

以下情况,JVM进程将被终止:

  • 程序运行结束
  • 程序运行到使用System.exit()或Runtime.getRuntime().exit()代码处结束程序。
  • 程序执行过程中遇到了未捕获的异常或错误而结束
  • 程序所在平台强制结束了JVM进程。

类加载机制与反射
类加载机制与反射
test1运行输出:7。 test2运行输出:6
引文两次运行Java程序处于不同的JVM中,两个JVM之间不会共享数据。虽然static静态变量共享同一块内存区。

对类进行初始化:加载、连接、初始化三个步骤

类的加载

  • 类的加载指:将类的class文件读入内存,并为之创建一个java.lang.Class对象。也就是说,当程序中使用任何类时,系统都会为之创建一个java.lang.Class对象。
  • 通过使用不同的类加载器,可以从不同来源加载类的二进制数据,来源有:
  • 从本地文件系统加载class文件
  • 从jar包加载class文件,JDBC编程时用到的数据库驱动类放在Jar文件中,JVM可以从Jar文件中直接加载该class文件。
  • 通过网络加载class文件
  • 把一个java源文件动态编译,并执行加载。

类的连接:
类被加载时候,系统为之生成对应的Class对象,接着将会进入连接阶段:负责把类的二进制数据合并到JRE中。
类的连接分为三个阶段:
(1)验证:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
(2)准备:负责为类变量分配内存,并设置默认初始值
(3)解析:将类的二进制数据中的符号引用替换成直接引用。

类的初始化
主要是对类变量进行初始化。对类对象初始化的方式有两种:
(1)声明类变量时指定初始值
(2)使用静态初始化块为类变量指定初始值
当程序主动使用任何一个类时,系统会保证该类以及所有的父类都会被初始化。

类初始化的时机:
当程序首次通过下面6中方式来使用某个类或接口时,系统会初始化该类和接口。
(1)创建类的实例:方式有:使用new操作符创建实例,通过反射来创建实例,通过反序列化来创建实例。
(2)调用某个类的类方法(静态方法)
(3)访问某个类或接口的类变量,
(4)使用反射方式来强制创建某个类

通过反射查看类信息

  • Java程序中的许多对象在运行时都会出现两种类型:**编译时类型和运行时类型。**例如:Person p = new Student().
    变量p编译时类型是:Person, 运行时类型是:Student。
  • 程序需要在运行时发现对象和类的真实信息。解决问题的方法有两种:
    (1)假设在编译时和运行时都完全知道类型的具体信息,可以先用instanceof运算符进行判断,再利用强制类型转换成其运行时类型的变量即可。
    (2)编译时无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,这就必须使用反射。

获得class对象
每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过该对象就可以访问JVM中的这个类。Java程序中获得Class对象的三种方式:
(1)使用Class类的forName(String clazzName)静态方法,该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(必须添加完整包名)
(2)调用某个类的class属性来获取该类对应的Class对象,例如:Person.class将会返回Person类对象。
(3)调用某个对象的**getClass()**方法。

方法(2)的优势: 代码更安全:程序在编译阶段就可以查看需要访问的Class对象是否存在。 程序性能更好:无须调用方法,所以性能更好。

一旦获得了某个类所对应的Class对象之后,程序就可以调用该对象的方法了。

反射机制
主要功能有:
得到一个对象所属的类;
获取一个类的所有成员变量和方法;
在运行时创建对象
在运行时调用对象的方法
非常重要的作用:在运行时动态的创建类的对象
类加载机制与反射
运行结果:Sub
获得class类的方法:
(1)class.forName(“类的路径”)
(2)类名.class
(3)实例.getClass()
Java中创建对象的方式:
(1)通过new
(2)通过反射
(3)通过clone()方法
(4)通过反序列化
clone()方法
Java处理基本数据类型(int, char, double等)时,采用按值传递。除此之外的其他类型都是按引用传递的方式。
函数调用和“=”赋值时也是引用传递。
类加载机制与反射
clone()方法的步骤:
(1)首先继承Cloneable接口(没有任何接口方法)
(2)在类中重写Object类的clone()方法
(3)clone方法中调用super.clone()方法

类加载机制与反射
类加载机制与反射
类加载机制与反射
当类中只有一些基本的数据类型时,采用浅复制。
当类中包含了一些对象时,就需要用到深复制了,实现方法:在对对象调用了clone()方法完成复制后,接着对对象中的非基本类型的属性也调用clone()方法完成深复制。
类加载机制与反射
类加载机制与反射
类加载机制与反射
类加载机制与反射