我很难理解静态类在以下场景中的使用方式。
假设我按如下方式声明了一个类:
public class TestLibrary {
private static final TestLibrary library = new TestLibrary();
private ErrorHandler errorHandler = null;
public static TestLibrary getLibrary() {
return library;
}
public ErrorHandler getErrorHandler() {
return errorHandler;
}
public int run(String[] args) {
this.initialize(args);
}
private void initialize(String[] data) {
library.errorHandler = new ErrorHandler();
}
}
我现在稍微将班级改为
private void initialize(String[] data) {
errorHandler = new ErrorHandler();
}
我在其他类中声明errorHandler,如下所示:
private ErrorHandler errorHandler = TestLibrary.getLibrary().getErrorHandler();
当我在其他类中使用errorHandler
的实例时,我的代码最终仍然起作用,但我不明白为什么。
问题1:第二种情况不应该创建new ErrorHandler
作为对象TestLibrary.errorHandler
而不是library.errorHandler
的一部分吗?
问题2:我做错了吗?你能详细说明一下吗?
答案 0 :(得分:0)
你所拥有的是一个静态方法getLibrary()
,它为所有调用者返回相同的实例。这被称为 Singleton - 虽然有更好的方法来编码它们。
然后你的假设Singleton(TestLibrary)展示了当被称为改变内部状态时的方法 - 最重要的是ErrorHandler
。
这会导致奇怪的行为,尤其是在多线程系统中。
这样的代码:
TestLibrary.getLibrary().run("".split(""));
ErrorHandler eh = TestLibrary.getErrorHandler();
assertEquals(eh, TestLibrary.getErrorHandler());
可能会失败。因为某人(意思是:某些其他线程)可能刚刚在第2行和第3行之间调用init(),导致ErrorHandler被设置为另一个值。
如果你需要在使用之前初始化你的TestLibrary,你应该一次,只做一次 - 所以你最好把它放到TestLibrary的构造函数中
如果您需要在代码中初始化不同的TestLibraries,则应删除Singleton模式并坚持使用
TestLibrary tl = new TestLibrary();
tl.run("".split(""));
在What is an efficient way to implement a singleton pattern in Java?
中详细了解Singleton