Java 如何在初始化类之前设置字段值?
我正在阅读关于java.sql.DriverManager的源代码,发现一些令人困惑的地方。以下是代码:Java 如何在初始化类之前设置字段值?,java,class,in-class-initialization,Java,Class,In Class Initialization,我正在阅读关于java.sql.DriverManager的源代码,发现一些令人困惑的地方。以下是代码: static { loadInitialDrivers(); println("JDBC DriverManager initialized"); } ...... public static void println(String message) { synchronized (logSync) { if (logWriter != null) {
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
......
public static void println(String message) {
synchronized (logSync) {
if (logWriter != null) {
logWriter.println(message);
// automatic flushing is never enabled, so we must do it ourselves
logWriter.flush();
}
}
}
在类初始化时没有设置logWriter,但是被它的静态块调用了。所以我看不到任何关于这个的日志信息。
如何在类初始化之前设置字段值?唯一的方法是在
驱动程序
实现中设置日志编写器
public class MyDriver implements Driver {
static {
// DriverManager will use ServiceLoader to load this class
DriverManager.setLogWriter(new PrintWriter(System.out));
}
... all methods in Driver
}
然后你会得到日志
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
编辑
对于@moilejter的问题,这里给出一个简单的示例,说明两个类如何相互调用,即使它们都没有准备好
public class JustTest {
public static void main(String[] args) throws java.lang.Exception {
A.i = 2;
}
}
class A {
static int i = 1;
static {
System.out.println("a block start");
B.print();
}
public static void print() {
System.out.println("a print: " + B.i);
}
}
class B {
static int i = 1;
static {
System.out.println("b block start");
A.print();
}
public static void print() {
System.out.println("b print: " + A.i);
}
}
唯一的方法是在
驱动程序
实现中设置日志编写器
public class MyDriver implements Driver {
static {
// DriverManager will use ServiceLoader to load this class
DriverManager.setLogWriter(new PrintWriter(System.out));
}
... all methods in Driver
}
然后你会得到日志
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
编辑
对于@moilejter的问题,这里给出一个简单的示例,说明两个类如何相互调用,即使它们都没有准备好
public class JustTest {
public static void main(String[] args) throws java.lang.Exception {
A.i = 2;
}
}
class A {
static int i = 1;
static {
System.out.println("a block start");
B.print();
}
public static void print() {
System.out.println("a print: " + B.i);
}
}
class B {
static int i = 1;
static {
System.out.println("b block start");
A.print();
}
public static void print() {
System.out.println("b print: " + A.i);
}
}
如果您使用
控制台
,则可以使用此代码:
DriverManager.setLogWriter(new PrintWriter(System.out));
如果您使用
控制台
,则可以使用此代码:
DriverManager.setLogWriter(new PrintWriter(System.out));
嗯-我没想到这会起作用,因为我认为调用setLogWriter()时对DriverManager的引用会迫使Java在调用setLogWriter()之前加载该类,而静态初始值设定项块会在加载该类时运行-所以,在调用setLogWriter之前…@moilejter不,你错了。类装入与类初始化不同。当
DriverManager
的静态块运行时,这意味着DriverManager
已加载,因为尚未准备就绪。其他类可以访问所有已初始化的内容。这就是为什么静态块是在logWriter
的定义下定义的。毕竟,自己做测试很容易。@moilejter我更新了我的答案,给你一个简单的例子。玩吧!对不起,你能给出一个完整的解决方案吗?我仍然不知道该怎么做。我只是写了一个新类,让它实现java.sql.Driver,然后我该怎么做?@DeanXu@JackZhou我认为你应该先学习JavaSPI
。然后通过SPI方式提供MyDriver
。我将在gist.Hmm中提供一个最小化的代码-我没有料到这会起作用,因为我认为调用setLogWriter()时对DriverManager的引用会迫使Java在调用setLogWriter()之前加载该类,而静态初始值设定项块会在加载该类时运行-因此,在你打电话给setLogWriter之前…@moilejter不,你错了。类装入与类初始化不同。当DriverManager
的静态块运行时,这意味着DriverManager
已加载,因为尚未准备就绪。其他类可以访问所有已初始化的内容。这就是为什么静态块是在logWriter
的定义下定义的。毕竟,自己做测试很容易。@moilejter我更新了我的答案,给你一个简单的例子。玩吧!对不起,你能给出一个完整的解决方案吗?我仍然不知道该怎么做。我只是写了一个新类,让它实现java.sql.Driver,然后我该怎么做?@DeanXu@JackZhou我认为你应该先学习JavaSPI
。然后通过SPI方式提供MyDriver
。我将在gist中提供一个最小代码。谢谢,但它不起作用。我可以看到“JDBC DriverManager initialized”谢谢,但它不起作用。我可以看到“JDBC DriverManager initialized”