在某个操作之后创建不可变对象

时间:2010-11-05 00:35:43

标签: java

我是Java的新手,所以我想知道它是否可以这样做? 我有一个文档对象说文档doc1 ..一旦我使用jdom构建器来构建这个对象我不希望它永远改变..它也需要始终可用..我相信后者可以使用静态关键字..如何确保一旦我使用jdom构建器,没有人可以修改此对象?所以在下面应该是类中的声明,以确保一旦我使用构建器构建它就无法修改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);

    }

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

所以简短的答案是否定的,你不能让它变成一成不变的。

理论上你可以创建自己的不可变类来镜像JDOM类,然后从他们的org.jdom对应物中精心初始化它们,但这将是一项过于艰苦的工作。

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

如果执行此操作(在性能或内存或两者中)太昂贵,您可以将此比较代码置于调试模式(例如,使用Java断言)。您还可以编写JUnit单元测试并将比较代码放入其中。

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

答案 2 :(得分:0)

是否符合您创建单身工厂的需求?在工厂中封装延迟实例化的实例。

由于工厂的客户端无法访问实例,因此无需将其标记为final。工厂本身可能是最终的。