Java 在特定操作后创建不可变对象

Java 在特定操作后创建不可变对象,java,Java,我是Java新手,所以我想知道是否可以这样做? 我有一个document对象,比如document doc1。。一旦我使用jdom构建器构建这个对象,我就不希望它被改变。。此外,它还需要始终可用。。我相信后者可以通过使用static关键字来实现。。如何确保一旦使用jdom构建器,就没有人可以修改这个对象?因此,在下面的示例中,类中的声明应该是什么,以确保在使用builder构建templateDocument后不能修改它 public static void createDocumentFrom

我是Java新手,所以我想知道是否可以这样做? 我有一个document对象,比如document doc1。。一旦我使用jdom构建器构建这个对象,我就不希望它被改变。。此外,它还需要始终可用。。我相信后者可以通过使用static关键字来实现。。如何确保一旦使用jdom构建器,就没有人可以修改这个对象?因此,在下面的示例中,类中的声明应该是什么,以确保在使用builder构建templateDocument后不能修改它

public static void createDocumentFromTemplate(StatusBuffer statusBuffer)
{
    //templateDocument = new Document();
    SAXBuilder builder = new SAXBuilder();
    Reader input = new StringReader(statusBuffer.toString());
    try {
        templateDocument = builder.build(input);
    } catch (JDOMException e) {
        final String message = "Error in building xml from output template";
        LOG.error(message, e);

    } catch (IOException e) {
        final String message = "Error in accessing output file template";
        LOG.error(message, e);

    }

您可以声明templateDocument
final
,这将阻止任何人重新分配引用。但是,这不会阻止他们设置templateDocument的成员字段。因此,如果templateDocument有一些您以前分配的成员字段,并且为该字段定义了一个公共setter,那么该字段仍然可以重新分配。

创建singleton工厂是否满足您的需要?封装工厂中延迟实例化的实例


因为工厂的客户端被阻止访问实例,所以不需要将其标记为final。工厂本身可能是最终的。

从调用builder.build()获得的org.jdom.Document是可变的。您可以将templateDocument设置为final,但这只会阻止您将另一个org.jdom.Document重新分配给它。您仍然可以调用templateDocument.removeContent(),或者在文档中查找元素并删除其子元素

所以简单的答案是不,你不能让它一成不变

理论上,您可以创建自己的不可变类来镜像JDOM类,然后从org.JDOM对应的类中费力地初始化它们,但这将是一项非常艰巨的工作

如果您只是试图检测文档中的错误突变,而它不是非常大,那么在调用builder.build()之后,您可以立即将文档序列化回XML字符串,并将其存储在变量中。代码运行后,可以将文档的最终状态序列化为另一个XML字符串,并比较这两个字符串以确保未进行任何更改

如果这样做成本太高(无论是在性能上还是在内存上,或者两者兼而有之),您可以将此比较代码置于调试模式(例如,使用Java断言)。您还可以编写JUnit单元测试并将比较代码放入其中


这个主题的一个变体是获取初始XML字符串和最终XML字符串的128位散列值,并比较它们,而不是实际的XML字符串。这样就不必存储初始字符串。

是的,我可以这样做。。但我希望这个对象在执行过程中保持不变。。所以我不能在方法中本地声明它,如果我在类中声明它,编译器会抱怨它没有初始化,如果初始化为null,我就不能执行builder.build(in)。。那么,在builder.build步骤完成后,如何创建一个对象并使其成为最终对象呢?我不希望任何人在builder.build(in)之后修改它?您需要做的是在create内部声明一个最终的局部变量,并将调用templateDocument的最终成员字段设置为该方法调用的结果。