1 简介
源码:
(1)Class.forName(String name)生成指定类名或接口名的类对象(Class)。与方法等价:Class.forName(className, true, currentLoader),
currentLoader即定义当前类的类加载器。
(2)Class.forName:在方法区生成java.lang.Class对象。即类加载过程:通过全限定名获取类的二进制字节流,将二进制字节流转化为方法区的运行时数据结构。
(3)生成Class对象后,即可执行不依赖对象的静态块代码,如MySQL驱动的加载。
2 static
调用时不依赖实例化的对象。
变量或方法使用static关键字,调用时,无需new对象,使用类名即可。
类加载时,根据生成的Class对象完成调用。
3 Usage
3.1 静态代码块
package com.monkey.java_study.common.entity;
/**
* User实体
*
* @author xindaqi
* @since 2021-01-23
*/
public class UserEntity {
/**
* 用户id
*/
private String uid;
/**
* 用户名称
*/
private String nickname;
/**
* 用户性别
*/
private String sex = "haha";
public UserEntity() {
}
static {
System.out.println(">>>>>>>>static function");
}
// 省略setter/getter/toString()
}
3.2 Class.forName()生成Class对象
使用Class.forName(String name)生成Class时,类加载过程中会直接调用静态代码块。
package com.monkey.java_study.database;
import com.monkey.java_study.common.entity.UserEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Class.forName测试.
*
* @author xindaqi
* @date 2021-12-30 17:35
*/
public class DriverLoaderTest {
private static final Logger logger = LogManager.getLogger(DriverLoaderTest.class);
public static void main(String[] args) throws Exception {
Class userClass = Class.forName("com.monkey.java_study.common.entity.UserEntity");
}
}
执行结果:
3.3 MySQL驱动加载
MySQL注册驱动时,通过Class.forName(“com.mysql.cj.jdbc.Driver”)即完成了驱动注册。
代码如下:
package com.monkey.java_study.database;
import com.monkey.java_study.common.entity.UserEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static com.monkey.java_study.common.constant.DatabaseConstant.*;
import static com.monkey.java_study.common.constant.DatabaseConstant.DB_MYSQL_PASSWORD;
/**
* Class.forName测试.
*
* @author xindaqi
* @date 2021-12-30 17:35
*/
public class DriverLoaderTest {
private static final Logger logger = LogManager.getLogger(DriverLoaderTest.class);
public static Connection databaseConnection() throws Exception {
// 注册MySQL驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 数据库连接地址
String DB_MYSQL_URL = "jdbc:mysql://localhost:3306/db_monkey_run?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";
// 数据库用户名
String DB_MYSQL_USER_NAME = "root";
//数据库密码
String DB_MYSQL_PASSWORD = "123456";
return DriverManager.getConnection(DB_MYSQL_URL, DB_MYSQL_USER_NAME, DB_MYSQL_PASSWORD);
}
public static void main(String[] args) throws Exception {
Class userClass = Class.forName("com.monkey.java_study.common.entity.UserEntity");
Connection connection = databaseConnection();
}
}
这是为什么?
因为Driver驱动类中有一段静态代码块。静态代码块中通过DriverManager完成驱动注册,即:java.sql.DriverManager.registerDriver(new Driver());
源码如下:
/*
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 2.0, as published by the
* Free Software Foundation.
*
* This program is also distributed with certain software (including but not
* limited to OpenSSL) that is licensed under separate terms, as designated in a
* particular file or component or in included license documentation. The
* authors of MySQL hereby grant you an additional permission to link the
* program and your derivative works with the separately licensed software that
* they have included with MySQL.
*
* Without limiting anything contained in the foregoing, this file, which is
* part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
* version 1.0, a copy of which can be found at
* http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
* for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.mysql.cj.jdbc;
import java.sql.SQLException;
/**
* 省略了注释
*/
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
/**
* Construct a new driver and register it with DriverManager
*
* @throws SQLException
* if a database error occurs.
*/
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}
4 小结
- 方法区:静态区。装载class文件,存储类信息、常量和静态变量;静态代码块同样存储与方法区,不依赖于实例化的对象;
- Class.forName即在方法区加载指定的类,生成Class对象,同时直接加载类的静态代码块。
【参考文献】
[1]https://blog.csdn.net/qq_22059611/article/details/84347957
[2]https://www.cnblogs.com/dolphin0520/p/3799052.html