北大荒建设集团有限公司网站,购买建立网站费怎么做会计凭证,手机能创建网站吗,四川网站建设咨询目录 1.类文件结构 2.类加载器
3.类加载的三个阶段 3.1加载 3.2链接 3.2.1验证 3.2.2准备阶段 3.2.3解析阶段 3.3初始化
4.拓展#xff1a;反射 4.1获取类对象 4.2创建实例 4.3获取方法 4.4方法调用 1.类文件结构 2.类加载器 类加载器用来将类文件的二进制字节码加载到JV…目录 1.类文件结构 2.类加载器
3.类加载的三个阶段 3.1加载 3.2链接 3.2.1验证 3.2.2准备阶段 3.2.3解析阶段 3.3初始化
4.拓展反射 4.1获取类对象 4.2创建实例 4.3获取方法 4.4方法调用 1.类文件结构 2.类加载器 类加载器用来将类文件的二进制字节码加载到JVM的方法区中。有四种类加载器 连接数据库驱动调用的类加载器在连接数据库时会调用DriverManager类进行驱动而DriverManager是核心类所以会使用到启动类加载器但数据库连接的驱动包并不在核心类库中所以DriverManager类中有一个loadInitialDrivers()方法内部使用了两种方式加载驱动 第一种是SPI机制加载驱动约定是在jar包中添加一个META-INF/services目录在其中添加一个配置文件文件的名称就是接口的全限定名称数据库连接驱动就是java.sql.Driver文件内容就是接口的实现类 通过ServiceLoader.load()方法根据约定的路径找到实现类这个load方法的内部调用的是线程上下文类加载器由于在创建线程时默认分配的是应用类加载器所以这种机制实际上调用的是应用类加载器。第二种是使用系统变量jdbc.drivers定义的驱动类的类名加载驱动调用Class.forName()方法加载和初始化驱动类使用的是系统类加载器也就是应用类加载器。 数据库连接驱动是先调用的系统类加载器再调用的应用类加载器所以在某些情况下会打破双亲委派机制。
3.类加载的三个阶段 类加载分为三个阶段加载、链接、初始化。链接又分为三个阶段验证、准备、解析。 3.1加载 要注意的是一个类的.class文件加载到方法区后变成了C的instanceKlass文件这个文件中包含了这个类的各种信息然后再在堆中生成一个Class类型的对象区分classclass是定义一个类用的区分.class文件这是编译生成的一个类的二进制字节码还没有被加载因为java不能直接访问方法区的instanceKlass所以需要这个Class副本来供我们使用通过反射拿到的一个类的Class对象就是这么来的这也就是为什么这个Class对象被叫做类镜像了下图的Person.class应该是Person的Class对象InstanceKlass中的_java_mirror存的是Class对象的指针。至于Class对象里有静态成员变量是因为在JDK8和以上版本中静态成员变量就被放在了Class对象的末尾也就是放到堆中了。 3.2链接 3.2.1验证 验证这个类转换的字节码是否符合JVM规范并进行安全性检查比如检查字节码中的魔数是否是Java文件的魔数。 3.2.2准备阶段 给静态变量分配空间并设置默认值
静态变量在JDK7和之前的版本中是放在instanceKlass的末尾也就是方法区中而从JDK8开始则是放在了类镜像末尾也就是堆内存中。静态变量的空间分配在准备阶段完成而赋值则是在初始化阶段但是final类型的静态变量比较特殊如果是final的基本类型或字符串类型的静态变量则分配空间和赋值都在准备阶段完成因为对于这些类型的变量而言final说明值不会改变已经确定了静态变量的值所以在准备阶段会直接赋值而如果是final的引用类型的静态变量则赋值会放在初始化阶段因为new一个对象需要类先初始化完成后才能创建。 3.2.3解析阶段 将常量池的符号引用解析为直接引用。符号引用就是这个类虽然被加载了但由于还没有进行解析也就不知道这个类在内存中的位置相当于只是一个符号而直接引用就是经过了解析之后知道了其在内存中的具体位置就可以访问这个类了。 3.3初始化 类的初始化是为了确保类的结构正确并且所有的数据都已初始化为预期的状态只有在类的初始化完成后才能在系统中正常使用这个类及其方法和属性。初始化过程主要包括给静态变量赋值、静态代码块的执行等只有首次主动使用时才会触发初始化初始化是懒惰的且只进行一次。 初始化发生的时机
main方法所在的类会先进行初始化。首次访问这个类的静态变量或静态方法时。子类进行初始化时若父类还没有初始化则会先进行父类的初始化再进行子类的初始化。当子类访问父类的静态变量时只会触发父类的初始化。当执行Class.forName方法时会执行类加载并默认进行初始化当然也可以给参数initialize设置为false表示不执行初始化。通过new创建实例化对象时会触发初始化。 以下情况不会触发初始化
访问静态常量时因为静态常量的空间分配和赋值均在链接时的准备阶段完成。使用类加载器的loadClass方法时loadClass方法只进行加载阶段。访问类对象的.class文件时不会触发初始化因为Class对象在class文件加载到方法区后就会生成所以在加载阶段时就已经生成。创建该类的数组不会触发初始化因为在JVM中会生成一个其他的类来表示数组类型与原本的类无关所以不会触发原来的类的初始化。
4.拓展反射 反射通过使用类对象即堆中的Class对象来创建实例、调用方法等。 4.1获取类对象
Class c类名.forName();
或
Class? c类名.class;
或
Class? c类名.getClass(); 以下操作都建立在获取了Class对象的基础上 4.2创建实例
Object oc.newInstance(); 也可以通过指定的构造器来创建实例比如使用String的构造器来创建实例
//先获取String类的带一个String类型参数的构造器
Constructor cstc.getConstructor(String.class); //再通过调用构造器的newInstance方法来创建实例
Object ocst.newInstance(abc); 4.3获取方法
//获取这个类的除继承父类的方法外的其他所有方法
Method[] m1c.getDeclaredMethods();//获取这个类的所有公有方法
Method[] m2c.getMethod(); //获取指定方法
Method mc.getMethod(方法名); 4.4方法调用
//先获取指定的方法
Method mc.getMethod(方法名); //调用方法
//当所调用的方法既有参数也有返回值时
Object resultm.invoke(参数集);//当所调用的方法没有返回值且无参数时
m.invoke(null);