1.什么是类加载?
直白的说,类加载就是将class文件读取到内存中,生成java.lang.Class实例。并完成类型合理性校验,初始化的过程。
类加载分为:
1.加载Load。读取class文件 生成Class实例
2.连接Link。连接又分为验证(校验信息是否正确,是否危害JVM安全)、准备(静态变量分配内存,默认0值初始化)、解析(类中的符号引用转换为直接引用)。
3.初始化Init。初始化就是类变量赋指定值、执行静态代码块。
2.init的执行时机?
init只有在类主动使用时才会触发。
1.new
2.访问类变量
3.反射
4.初始化子类
5.jvm启动时表明启动类
3.为什么需要Class
类已经是事务的抽象,为什么还需要Class?
我们理解的类是对真实事务的一种抽象。但是类都是以Class实例的方式存在。这样JVM才能通用的解析类,调用类的方法,属性。
2.类加载的作用?
将.class文件加载到内存中。
3.类加载的方式
1.命令行启动JVM初始化加载
2.Class.forName()加载。DBC 4.0 Drivers 之后可以不进行配置。详细参见:JAVA拾遗–关于SPI机制,这篇文章很有营养。
3.ClassLoader.loadClass()加载。
4.后两种加载方式的区别
Class.forName()会执行类的静态代码块,而ClassLoader不会。只加载静态代码块。
5.jdbc中为什么使用Class.forName()
JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC Driver的 Driver类的代码都必须类似如下:
public class MyJDBCDriver implements Driver {
static {
//这里Driver供应商已经默认注入了一个驱动,所以不需要new instance
//只需要利用Class.forName()执行初始化操作,执行静态代码块,jdbc4之后采用SPI不需要。
DriverManager.registerDriver(new MyJDBCDriver());
}
}
6.new 和 newInstance的区别?
1.new是强类型校验,可以调用任何构造方法。在使用时类可以未被加载。
2.newInstance是弱类型校验,只能调用无参构造方法。在使用时必须保证类被加载。
7.利用newInstance可以解耦
java通过类加载器把类的实现与类的定义进行解耦,所以是实现面向接口编程、依赖倒置的必然选择。 -码出高效:java开发手册
可以参考Spring 程序间的耦合和解耦。
不解耦手段写jdbc:
DriverManager.registerDriver(new com.mysql.jdbc.Driver())
Connection conn = DriverManager.getConnection(url,username,password);
这样一来,如果mysql包还未导入程序会报错,且如果决定换用其他驱动就必须改代码了。这样就会存在耦合。
下面利用Class.forName解耦。
Class.forName("com.mysql.jdbc.Driver");
代码中只需要类的权限定名即可,避免new。
参考:
1.java类的加载机制
2.JAVA拾遗–关于SPI机制
3.为什么jdbc 只是需要class.forName()
4.Spring 程序间的耦合和解耦
5.码处高效:java开发手册