打算做一个数据库连接池的实现,结果遇到了对java运行顺序理解的困惑。麻烦大家帮忙看看,具体问题在下面给出。
这个是工具类。
package com.jdbc.comm; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.jdbc.connection.DataSource; public class JdbcUtils { //非常不解,这一步为什么要在static块前运行!!! //初始化的时候应该是静态方法(包括静态块)要在非静态属性前面嘛! private DataSource dataSource = new DataSource(); private JdbcUtils() { } private static JdbcUtils instance = new JdbcUtils(); public static JdbcUtils getInstance() { return instance; } static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public Connection getConnection() throws SQLException { Connection conn = dataSource.getConnection(); return conn; } public void free(Connection conn, PreparedStatement ps, ResultSet rs) { try { if (rs != null) { rs.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (ps != null) { ps.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (conn != null) { dataSource.free(conn); } } } } }
这个是自己写的一个DataSource。
package com.jdbc.connection; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.LinkedList; public class DataSource { private Connection conn = null; private String url = "jdbc:mysql://localhost:3306/jdbc"; private String username = "root"; private String password = "zzx"; private int maxCount = 5; private int currentCount = 0; private LinkedList<Connection> connectionPool = new LinkedList<Connection>(); public DataSource(){ this.createConnection(); } private LinkedList<Connection> createConnection(){ try { for(int i=0;i<maxCount;i++){ conn = DriverManager.getConnection(url, username, password); currentCount++; connectionPool.addLast(conn); } return connectionPool; } catch (SQLException e) { e.printStackTrace(); } return null; } public Connection getConnection(){ if(conn != null){ conn = connectionPool.removeFirst(); currentCount--; } return conn; } public void free(Connection conn){ if(currentCount < maxCount){ connectionPool.addLast(conn); currentCount++; } } }
下面这个是测试代码
package com.jdbc.test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.jdbc.comm.JdbcUtils; public class DataSourceTest { public static void main(String[] args) throws SQLException{ Connection conn = null; PreparedStatement ps =null; ResultSet rs = null; JdbcUtils jdbcUtils = JdbcUtils.getInstance(); for(int i=0;i<10;i++){ conn = jdbcUtils.getConnection(); System.out.println(conn); } } }
这个程序运行出错,我已经知道出错的地方,简单来说就是Class.forName("com.mysql.jdbc.Driver")出现在conn = DriverManager.getConnection(url, username, password)后面,所以抛了异常。我也知道怎么改,但是我非常想不通的一点就是,当条用jdbc的构造函数的时候,为什么不先执行JdbcUtils里的静态块,而是先实例化了DataSource。
本人很菜,麻烦各位指点一下。
问题补充:
我觉得是这样的
当程序启动的时候 会先将你的static代码块放在内存中一个单独的static区
会并且会先帮你把DataSource 给new出来放在堆内存
当你getInstance的时候其实DataSource对象已经先实例化好了
(因为你用了单例 所以当你通过getInstance加载jdbcutil实例的时候 才会执行static区的代码)
谢谢你的回答,
但是有点搞不懂啊,他放到内存就等于new了一个啦?那么程序的运行顺序就应该改成,非静态属性>静态方法了啊。