• Post Reply Bookmark Topic Watch Topic
  • New Topic

How do we freeze an object while constructing an object using JavaBeans pattern.  RSS feed

 
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

In Effective Java, item 2 - "Consider a builder when faced with many constructor parameters", Joshua Bloch explains the drawbacks of constructing an object that has many required and optional parameters using Telescopic pattern ( create a constructor with required parameters, create one constructor each for each optional parameter and chain them so in the end we have a constructor that has every parameter ) and the JavaBeans pattern ( construct an object using no parameter contsructor and then set the properties using setter methods ).

The author states that the drawback of using JavaBeans pattern is that an object may be in an inconsistent state partway through the construction and with javabeans pattern, we cannot make our class immutable. I have understood this much.

And then the author says that we can reduce these drawbacks by "freezing" the object when its construction is complete and not allowing it to be used until frozen. Does the author mean freeze the object by synchronizing access or something? The author also suggests later why this approach also wouldn't work. I have not understood that part too cause I have not understood how freezing works.

How do we 'freeze' an object? Following is a line from the book -
"Moreover, it can cause errors at runtime, as the compiler cannot ensure that the programmer calls the freeze method on an object before using it."

Is there a freeze method really? Which class has the freeze method? Is it deprecated now? I can't find it. I have never even come across it. The Object class does not have a freeze method, it seems.

Would you know? Please help.

Thanks,
Chan.
 
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't have Effective Java, Second Edition (which is what you have), so I can't look up what the book says exactly, but there is certainly no special "freeze" method or built-in mechanism in Java to freeze an object.
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Jesper. I thought so too, but I thought it better to confirm.

Still wondering though how we'd freeze an object using user methods. Must be synchronization he is referring to? Or can there be some other style too to freeze and unfreeze an object? External synchronization doesn't seem like a graceful way of freezing and unfreezing. Not sure if it is something that can be done correctly even with synchronization even with the simplest of classes.

Anyone who has ever come across this freezing and unfreezing of objects manually? Must be kind of unpopular?

Thanks,
Chan.
 
Author and ninkuma
Marshal
Posts: 66307
152
IntelliJ IDE Java jQuery Mac Mac OS X
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Frankly, I've never heard of it, and never had any problems with not hearing of it.
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Bear. Then I won't even try to find out.

Chan.
 
Ranch Hand
Posts: 3090
14
  • Likes 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I suspect the "freeze" stuff was written in response to Ruby, which gained a lot of popularity in the time between the first and second edition of Effective Java. (The section on the builder pattern wasn't even in 1st edition; neither was the mention of freezing.) Anyway, Ruby has a freeze method on all objects, though its use is not very popular, for reasons which escape me. Ruby users are used to not having any compile-time enforcement of anything anyway, so Bloch's objection doesn't really apply there. But he's explaining why he thinks this is not a viable option for Java.

Here's a sketch of what it could look like, though:

I haven't analyzed it carefully, but I believe it should work under multithreading. Sure, it's tedious to write, but so are most POJOs in Java; gratuitous verbosity is a standard feature of Java. The main problem is as Bloch says; there's no way for the compiler to tell the difference between a frozen object and one that's not. It's only known at runtime.
 
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:Here's a sketch of what it could look like, though:

@Chan: And furthermore, you could write it as an interface that all "Freezable" objects implement.

BTW: <nitpick>I think it would be better to make 'frozen' volatile.</nitpick>

Winston
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:BTW: <nitpick>I think it would be better to make 'frozen' volatile.</nitpick>

Yeah, I considered that too, but then I think you need to insert a read on the volatile variable in each getter as well, as a memory barrier, to prevent some out-of-order read from fetching a cached value from before the freeze. I thought "synchronized" would communicate intent more clearly, and I'm more confident in its correctness, so I went with that.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alternately, I suppose we could make *all* the fields volatile, and drop all synchronization. That would work nicely.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:Alternately, I suppose we could make *all* the fields volatile, and drop all synchronization. That would work nicely.

I think you still need to synchronize freeze(), but not anything else methinks.

Winston
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is interesting, Mike & Winston. Thank you so much for that example and explanation.

This really looks like an ungraceful and bad looking way to construct objects. First we have to do a freeze check during construction.
Granted, this window might be a small window. But consider this.
If this class were to have other methods ( non-setter methods ) too, we'd not only have to make those methods synchronized
( or use some other synchronization tool ), but also check if the object was frozen.
And if the freeze check is not done, even a synchronized method alone is broken.

Since this freeze check is not something that the compiler can enforce, it's quite a risky way to construct objects.
So I get it why we should never construct objects in this way. I think I'm getting it now.
Or was that all wrong? :-)

you could write it as an interface that all "Freezable" objects implement.

This is very interesting too. Even Joshua Bloch suggests the same style of coding for build method implementation.

Thank you,
Chan.
 
Rancher
Posts: 2762
32
Eclipse IDE Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you have AOP, or you have a factory for your objects, You could write an annotation that supports freezable. If you do have to support freezing, it seems like freezeability is a cross cutting concern. You would need a large number of classes that will need to be frozen. Also, remember that if you have a deep hierarchy of objects, you would need to freeze the whole hierarchy. If the user can do Foo.getbar().setA(...) on a frozen foo. It's not really frozen. So, the Bar class will need to be freezable, and foo will have t freeze bar. I am assuming that you are going to use this in POJOs only in which relationship between classes is always a Has a relationship and never a Uses relationship, so the entire POJO hierarchy will need to be freezable. A lot of boilerplate code in hundreds of classes in a big sized project.

So, going back to using an annotation, if you have AOP, you could annotate your classes with your custom freezable annotation. Then you can implement a Before annotation that checks if the object is frozen for setmethods. Also, for get methods, it will need to return a frozen version of the child object.

If you have your own factory, the factory can return a proxy that works similar to the annotation. It can intercept the set methods and check if the object is frozen. It can intercept get methods and return frozen version of child objects
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Chan Ag wrote:This really looks like an ungraceful and bad looking way to construct objects.

Yup; although I have used it once - to create a class similar to java.util.regex.Pattern that is cached and has a fluent interface, viz:

Regex.find("CAT").ignoreCase().in("The flat cat sat on the mat");

The reason being that a Pattern can take a fair bit of construction, so you need to be sure that it's frozen before you use it. You also don't want to cache it until it's frozen.

I guess what you need to ask yourself is: do you really need the JavaBean pattern for construction? From what I can gather it's perfectly possible to create "Bean-like" objects with a Builder - although I'm admittedly not an expert - and it saves all that faffing about associated with freezing.

Mind you, I'm biased because I far prefer immutable objects.

Winston

PS: I should add that about 2 months after I created my Regex class, I discovered that someone else had done pretty much exactly the same thing, so I was actually re-inventing the wheel. It was a fun class to write though, and I do find it very useful.
 
Jayesh A Lalwani
Rancher
Posts: 2762
32
Eclipse IDE Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hmm that's interesting. So, you used this to implement a Flyweight pattern. Yes, I can see the utility of this pattern in implementing FlyWeight.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jayesh A Lalwani wrote:Hmm that's interesting. So, you used this to implement a Flyweight pattern. Yes, I can see the utility of this pattern in implementing FlyWeight.

I didn't think of it that way, but yes, I guess so.

It just struck me that String is the wrong class to implement pattern-matching from, since it's the pattern (java.util.regex.Pattern) - and more importantly, the compiled Pattern - that's important, not the String. And since I've always been partial to fluent interfaces, it seemed like a good place to flex me "fluenting" muscles.

And it is significantly faster than the on-the-fly String methods, at least for "normal"-size Strings.

Like I say, someone beat me to it though.

Winston
 
Chan Ag
Rancher
Posts: 1090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I sometimes feel I keep saying thanks every now and then and it must annoy people at times, but thanks. :-)

 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:Alternately, I suppose we could make *all* the fields volatile, and drop all synchronization. That would work nicely.

On second thought, I retract this. In each setter, there's a gap between checkNotFrozen() and the setting of the variable; this means that another thread could call freeze() in that gap, and the value could be observed to change after the freeze.

On the other hand, a typical model for using either freeze() or the builder pattern would be to construct the object in one and only one thread, then publish the immutable version to the other threads. As, for example, the way we typically use StringBuilder and String. We don't worry that StringBuilder is unsafe for multithreading; we only publish the immutable String version. Using this model, it is tempting to think that maybe synchronizing only the freeze() would be enough, as Winston suggests. And maybe it is. But I'm not sure. It doesn't seem to satisfy the criteria for safe publication laid out in Java Concurrency in Practice, 3.5.3:
To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

* Initializing an object reference from a static initializer.
* Storing a reference to it into a volatile field.
* Storing a reference to it into a final field.
* Storing a reference to it into a field that is properly guarded by a (synchronized) lock.

Simply using a synchronized lock somewhere after construction does not appear to be enough. I guess we could do something like this though:

This seems to satisfy the criteria, provided other threads only access the reference returned by freeze(). Much like the builder pattern. I also removed the isFrozen() since only the constructing thread should ever see the unfrozen instance; from that thread, there should be no question whether freeze has been called yet or not.

I don't suppose this really matters, as there's still no advantage of using this technique instead of builder; both are equally onerous to write, and builder is definitely easier to use safely. The beauty of Ruby's build() method is that it's a standard method available on any object; you don't *need* to write it yourself. In Java that's not the case, so there's really no point, I think.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:This seems to satisfy the criteria, provided other threads only access the reference returned by freeze().

Another alternative (which I used in my Regex class) is to make sure that any usage method freezes the object before it runs, viz, using your example:but there are oodles of ways to do it.

Winston
 
Greenhorn
Posts: 1
Java Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Chan,

the word "frozen" in Effective Java is used to explain the fact that final field variables can only be assigned
during constructor time.
The pattern described in this very article passes a builder object to the constructor of the nutrition and the static field variables are set within.
Afterwards the nutrition object is immutable.


 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sven Thoden wrote:the word "frozen" in Effective Java is used to explain the fact that final field variables can only be assigned
during constructor time.

No, this is definitely not what is being said in Effective Java. We're talking about Item 2, page 13. "Freezing" is used during the discussion of the second alternative, the JavaBeans pattern - just before discussion of the third alternative, the builder pattern. Freezing is not part of the builder pattern. If final variables were used (as in builder), freezing would be unnecessary, and the compiler would be able to tell whether a given field had been set or not. Which is contrary to what Effective Java says there. You need to read it more carefully.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!