Creating an immutable object after a certain operation
I'm new to Java so I wanted to know whether its possibl开发者_运维问答e to do this ? I have a document object say Document doc1 .. once I use a jdom builder to build this object I don't want it to be changed ever .. also it needs to be always available .. i believe the latter can be done using the static keyword .. how do I make sure that once I use the jdom builder no one can ever modify this object ? So in the following what should be the declaration in the class to make sure templateDocument cannot be modified once I build it using builder ..
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);
}
You can declare templateDocument final
, which will prevent anyone from re-assigning the reference. It won't however, prevent them from setting the member fields of templateDocument. So if templateDocument has some member field that you assigned before, and has a public setter defined for that field, then that field can still be re-assigned.
The org.jdom.Document you get from calling builder.build() is mutable. You can make templateDocument final, but that only prevents you from reassigning another org.jdom.Document to it. You could still call templateDocument.removeContent(), or find an Element in the Document and remove its children.
So the short answer is no, you can't make it immutable.
In theory you could create your own immutable classes that mirror the JDOM classes, then painstakingly initialize them from their org.jdom counterparts, but that would be excessively hard work.
If you're just trying to detect erroneous mutations to your Document, and it's not terribly huge, immediately after the call to builder.build() you could serialize the Document back to an XML String and store that in a variable. Once your code runs, you can then serialize the final state of the Document to another XML String and compare the two Strings to ensure no changes have been made.
If it would be too expensive to do this (either in performance or memory or both), you can put this comparison code into a debug mode (eg, using Java assertions). You could also write JUnit unit tests and put the comparison code in them.
A variation on this theme would be to take 128-bit hash values of the initial and final XML Strings and compare those, rather than the actual XML Strings. This saves you from having to store the initial String.
Would it meet your needs to create a singleton factory? Encapsulate the lazily instantiated instance in the factory.
Because clients of the factory are prevented from accessing the instance it would not need to be marked as final. The factory itself could be final.
精彩评论