Class.forName和newInstance两个方法

本文深入探讨Java反射机制的应用,通过具体示例说明如何利用Class.forName方法加载类并实例化对象,进一步介绍该方法在JDBC中加载数据库驱动的过程,并提供了一个完整的使用JDBC进行数据库操作的示例。

Class.forName(String className)这个方法传入一个类型的全路径的名字(也就是带包的完整名字),会返回一个字节码类型(也就是Class类型)的实例

如:Class clazz = Class.forName("com.dean.Person");

然后再用这个字节码类型的实例clazz调用newInstance()方法会返回一个Object类型的对象

如下:Object object = clazz.newInstance();

这个object当然不能直接调用Perosn类的方法了,因为他是Object类型

这个时候就需要强制类型转换了

Person person = (Perosn)clazz.newInstance();

下面再解释一个加载数据库驱动时不用newInstance方法的原因:

如下:

Class.forName("com.mysql.jdbc.Driver");

并没有写成:

Driver driver = (Driver)Class.forName("com.mysql.jdbc.Driver").newInstance();

DriverManager.registerDriver(driver);

不过我再查看com.mysql.jdbc.Driver类的源码时发现了:

static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}

我的理解是这样的,当Class.forName("com.mysql.jdbc.Driver");被执行到时相当于com.mysql.jdbc.Driver的字节码实例被加载到内存了

而按照类的初始化顺序静态代码块也应该被执行了,也就是说Class.forName("com.mysql.jdbc.Driver");看似一句实际上相当于下面两句

Class.forName("com.mysql.jdbc.Driver");

java.sql.DriverManager.registerDriver(new Driver());

所以大多数jidbc连接代码写完Class.forName("com.mysql.jdbc.Driver");这句就去拿数据库连接了,几乎看不到注册驱动的代码。

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
 
public class MysqlDemo {
    public static void main(String[] args) throws Exception {
        Connection conn = null;
        String sql;
        //下面语句之前就要先创建javademo数据库
        String url = "jdbc:mysql://localhost:3306/javademo?"
                + "user=root&password=root&useUnicode=true&characterEncoding=UTF8";
        try {
            //动态加载mysql驱动
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("成功加载MySQL驱动程序");
            //一个Connection代表一个数据库连接
            conn = DriverManager.getConnection(url);
            Statement stmt = conn.createStatement();
            sql = "create table student(NO char(20),name varchar(20),primary key(NO))";
            int result = stmt.executeUpdate(sql);// 
            if (result != -1) {
                System.out.println("创建数据表成功");
                sql = "insert into student(NO,name) values('2012001','陶伟基')";
                result = stmt.executeUpdate(sql);
                sql = "insert into student(NO,name) values('2012002','周小俊')";
                result = stmt.executeUpdate(sql);
                sql = "select * from student";
                ResultSet rs = stmt.executeQuery(sql);
                System.out.println("学号\t姓名");
                while (rs.next()) {
                    System.out
                            .println(rs.getString(1) + "\t" + rs.getString(2));
                }
            }
        } catch (SQLException e) {
            System.out.println("MySQL操作错误");
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.close();
        }
    }
}

### Java 中 `Class.forName(className).newInstance()` 的作用与用法 `Class.forName(className).newInstance()` 是 Java 反射机制中的一种常见用法,主要用于动态加载类并创建类的实例。该方法组合了两个关键步骤:通过类名加载类并实例化该类。 #### 作用 1. **动态加载类** `Class.forName(className)` 会根据传入的字符串参数(类的全限定名)加载对应的类。这个过程包括类的加载、链接初始化[^4]。例如,如果类中包含静态代码块或静态变量初始化逻辑,这些代码会在类加载时执行。 2. **创建类的实例** `newInstance()` 方法用于调用类的无参构造函数来创建类的一个实例。如果类没有默认的无参构造函数,或者构造函数不可访问,则会抛出异常[^2]。 #### 用法 `Class.forName(className).newInstance()` 的典型使用场景包括: - 动态加载数据库驱动(如 JDBC 驱动)。 - 实现插件化架构,根据配置文件动态加载模块。 - 在框架中实现通用的实例化逻辑。 #### 示例 以下是一个简单的示例,演示如何使用 `Class.forName(className).newInstance()` 动态加载类并创建实例: ```java public class Example { static { System.out.println("静态代码块执行"); } public Example() { System.out.println("构造函数执行"); } public void sayHello() { System.out.println("Hello from Example"); } } public class Main { public static void main(String[] args) { try { // 动态加载类并创建实例 Class<?> clazz = Class.forName("Example"); Object instance = clazz.newInstance(); // 调用方法 java.lang.reflect.Method method = clazz.getMethod("sayHello"); method.invoke(instance); } catch (Exception e) { e.printStackTrace(); } } } ``` 输出结果: ``` 静态代码块执行 构造函数执行 Hello from Example ``` #### 注意事项 - `Class.forName(className).newInstance()` 要求类必须有无参构造函数,否则会抛出 `InstantiationException` 或 `IllegalAccessException`。 - 如果需要调用带参数的构造函数或私有构造函数,应使用 `Constructor.newInstance()` 方法。 - `Class.forName()` 会触发类的静态初始化,而 `ClassLoader.loadClass()` 不会触发静态初始化[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值