Java - 导入项目中的静态初始值设定项
Java - static initializers in imported projects
所以我有两个项目 A 和 B,项目 B 是在项目 A 中导入的,在项目 B 中我想初始化一些具有静态初始化器的对象。
问题是,他们没有被调用(已经用 final
关键字测试过,没有帮助)。
所以我实际上想要一个小系统,它应该是这样的(这里描述的每个 class 都在项目 B 中):
- class A 是一个主要的 class,您可以在其中调用方法
addClassToLoad()
* 来添加其他 classes(这将是 "loaded"当 class A 中的方法 start()
被调用时);
- classes B、C 和 D 从其静态初始值设定项调用方法
addClassToLoad()
;
- 当项目 A 中的某些 class 调用方法
start()
时,class A 列出它已获得的所有 class 并调用方法 onLoad()
(在 * 中解释)。
而且每个方法都是静态的,所以它只能是一个(没有 "instancing")。
遗憾的是,没有调用静态初始化程序。
问题是:我是不是做错了什么(或者根本不可能),或者有其他方法可以做这个小系统? (我只是不想在 class A 中写关于每个 class,必须在 start()
方法中加载)
*addClassToLoad()
采用具有一个方法 onLoad()
的接口,因此在 class A
中调用方法 start()
时会调用它
代码版本:
class答:
public class A {
private static ArrayList<ClassToLoad> classesToLoad;
public static void addClassToLoad(ClassToLoad c) {
if (classesToLoad == null)
classesToLoad = new ArrayList<ClassToLoad>();
classesToLoad.add(c);
}
public static void start() {
for (ClassToLoad c : classesToLoad) {
c.onLoad();
}
}
}
class B(以及其他(C、D 等)像这样的):
public class B {
static {
A.addClassToLoad(new ClassToLoad() {
public void onLoad() {
load();
}
});
}
private static void load() {
// do something here on load ...
}
}
class ClassToLoad:
public interface ClassToLoad {
public void onLoad();
}
添加新的 JDBC 驱动程序时会出现同样的问题,为什么必须调用 Class.forName() 来注册 JDBC 驱动程序。每个 JDBC 驱动程序 class 都有一个静态初始化程序来向 DriverManager 注册自己。为什么? class 加载程序默认不会加载 jar 文件中的所有 classes。 class 仅在执行期间被引用时才加载,这很聪明,因为 class 加载器永远不必将那些未使用的 class 加载到内存中。因此,要解决您的问题,您必须设法加载那些 classes,例如在调用 start() 之前通过 Class.forName()。如果您使用 spring,您可以在配置中创建所有这些 class 的列表。 Spring 还提供了一个实用程序来扫描特定类型的包 classes,然后您只需指定要扫描的包名称即可。
当 ClassLoader 第一次加载 class 时,将设置静态字段和静态初始值设定项(静态块)。请记住,这将在给定 class 首次使用时发生,因为 ClassLoader 以惰性方式加载 classes(需要时)
所以我似乎不可能执行那些静态块,所以我将我需要加载的每个 class 添加到 class A 中,这样它们实际上是加载没有任何问题(在项目 B 中)。在项目 A 中,我需要在主 class 中添加我需要加载的其他 classes,显然。
所以我将这些 classes 作为单例,所以它们实际上已经加载并准备好进行 "main" 加载、启动和处理。所以添加 class 看起来像这样:
A.addClassToLoad(B.getInstance());
我使用 class ClassToLoad
作为通用 class 来加载(听起来很有趣),尽管我将其重命名为 SystemCycle
.
因此 class B 的示例代码现在如下所示:
public class B implements SystemCycle {
private static B instance = new B();
private B() {}
public static void getInstance() {
return instance;
}
public void onLoad() { /* some code here */ }
public void onLaunch() { /* some code here */ }
public void onDispose() { /* some code here */ }
}
而 SystemCycle
class 现在看起来像这样:
public interface SystemCycle {
public void onLoad();
public void onLaunch();
public void onDispose();
}
嗯,这很明显,因为 class B.
的例子
我什至做了一个小检查系统,所以如果用户试图调用这些方法之一,它将被忽略,因为 class 实现 SystemCycle
检查是否 class A此时实际上正在装载、发射或处置。但如果没有,它就可以做到return
。 (尽管如果 usermade class 不检查,它可能会被其他 usermade class 滥用)。
P.S. addClassToLoad
在我的项目中其实是叫addSystemToLoad
,所以我这里这样写是为了方便举个例子了解一下。
小编辑:我什至先尝试了一些与注释有关的东西,但即使那样也没有帮助我。
所以我有两个项目 A 和 B,项目 B 是在项目 A 中导入的,在项目 B 中我想初始化一些具有静态初始化器的对象。
问题是,他们没有被调用(已经用 final
关键字测试过,没有帮助)。
所以我实际上想要一个小系统,它应该是这样的(这里描述的每个 class 都在项目 B 中):
- class A 是一个主要的 class,您可以在其中调用方法
addClassToLoad()
* 来添加其他 classes(这将是 "loaded"当 class A 中的方法start()
被调用时); - classes B、C 和 D 从其静态初始值设定项调用方法
addClassToLoad()
; - 当项目 A 中的某些 class 调用方法
start()
时,class A 列出它已获得的所有 class 并调用方法onLoad()
(在 * 中解释)。
而且每个方法都是静态的,所以它只能是一个(没有 "instancing")。
遗憾的是,没有调用静态初始化程序。
问题是:我是不是做错了什么(或者根本不可能),或者有其他方法可以做这个小系统? (我只是不想在 class A 中写关于每个 class,必须在 start()
方法中加载)
*addClassToLoad()
采用具有一个方法 onLoad()
的接口,因此在 class A
start()
时会调用它
代码版本:
class答:
public class A {
private static ArrayList<ClassToLoad> classesToLoad;
public static void addClassToLoad(ClassToLoad c) {
if (classesToLoad == null)
classesToLoad = new ArrayList<ClassToLoad>();
classesToLoad.add(c);
}
public static void start() {
for (ClassToLoad c : classesToLoad) {
c.onLoad();
}
}
}
class B(以及其他(C、D 等)像这样的):
public class B {
static {
A.addClassToLoad(new ClassToLoad() {
public void onLoad() {
load();
}
});
}
private static void load() {
// do something here on load ...
}
}
class ClassToLoad:
public interface ClassToLoad {
public void onLoad();
}
添加新的 JDBC 驱动程序时会出现同样的问题,为什么必须调用 Class.forName() 来注册 JDBC 驱动程序。每个 JDBC 驱动程序 class 都有一个静态初始化程序来向 DriverManager 注册自己。为什么? class 加载程序默认不会加载 jar 文件中的所有 classes。 class 仅在执行期间被引用时才加载,这很聪明,因为 class 加载器永远不必将那些未使用的 class 加载到内存中。因此,要解决您的问题,您必须设法加载那些 classes,例如在调用 start() 之前通过 Class.forName()。如果您使用 spring,您可以在配置中创建所有这些 class 的列表。 Spring 还提供了一个实用程序来扫描特定类型的包 classes,然后您只需指定要扫描的包名称即可。
当 ClassLoader 第一次加载 class 时,将设置静态字段和静态初始值设定项(静态块)。请记住,这将在给定 class 首次使用时发生,因为 ClassLoader 以惰性方式加载 classes(需要时)
所以我似乎不可能执行那些静态块,所以我将我需要加载的每个 class 添加到 class A 中,这样它们实际上是加载没有任何问题(在项目 B 中)。在项目 A 中,我需要在主 class 中添加我需要加载的其他 classes,显然。
所以我将这些 classes 作为单例,所以它们实际上已经加载并准备好进行 "main" 加载、启动和处理。所以添加 class 看起来像这样:
A.addClassToLoad(B.getInstance());
我使用 class ClassToLoad
作为通用 class 来加载(听起来很有趣),尽管我将其重命名为 SystemCycle
.
因此 class B 的示例代码现在如下所示:
public class B implements SystemCycle {
private static B instance = new B();
private B() {}
public static void getInstance() {
return instance;
}
public void onLoad() { /* some code here */ }
public void onLaunch() { /* some code here */ }
public void onDispose() { /* some code here */ }
}
而 SystemCycle
class 现在看起来像这样:
public interface SystemCycle {
public void onLoad();
public void onLaunch();
public void onDispose();
}
嗯,这很明显,因为 class B.
的例子我什至做了一个小检查系统,所以如果用户试图调用这些方法之一,它将被忽略,因为 class 实现 SystemCycle
检查是否 class A此时实际上正在装载、发射或处置。但如果没有,它就可以做到return
。 (尽管如果 usermade class 不检查,它可能会被其他 usermade class 滥用)。
P.S. addClassToLoad
在我的项目中其实是叫addSystemToLoad
,所以我这里这样写是为了方便举个例子了解一下。
小编辑:我什至先尝试了一些与注释有关的东西,但即使那样也没有帮助我。