jQuery in Action, 2nd edition*
The moose likes Features new in Java 8 and the fly likes What are Value based classes? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Java » Features new in Java 8
Bookmark "What are Value based classes?" Watch "What are Value based classes?" New topic
Author

What are Value based classes?

Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
Yesterday I was trying to understand the Lambda Expression use case example given here .

To illustrate what is said, the tutorials have a use-case that has a class Person.java

Now in this class, we see the references of a class called java.time.LocalDate

http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html page suggests that LocalDate is a value based class.

The tutorials suggest that the value based classes have the following properties. This I have been trying to understand. I think I understand some of it. But the rest of it....

Value-based Classes

Some classes, such as java.util.Optional and java.time.LocalDateTime, are value-based. Instances of a value-based class:

are final and immutable (though may contain references to mutable objects);
have implementations of equals, hashCode, and toString which are computed solely from the instance's state and not from its identity or the state of any other object or variable;
make no use of identity-sensitive operations such as reference equality (==) between instances, identity hash code of instances, or synchronization on an instances's intrinsic lock;
are considered equal solely based on equals(), not based on reference equality (==);
do not have accessible constructors, but are instead instantiated through factory methods which make no committment as to the identity of returned instances;
are freely substitutable when equal, meaning that interchanging any two instances x and y that are equal according to equals() in any computation or method invocation should produce no visible change in behavior.
A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism. Use of such identity-sensitive operations on instances of value-based classes may have unpredictable effects and should be avoided.


I didn't get what are final instances. We know we can create final variables, but what are final instances? I get the immutable part. I created a LocalDate type variable and assigned it a LocalDate object. Then I assigned it another object. I could do that. Yeah I wouldn't be able to do that if the variable was final. so what are final instances. I get the immutable part.

Rule 2 states that "have implementations of equals, hashCode, and toString which are computed solely from the instance's state and not from its identity or the state of any other object or variable;". But isn't that also how most other classes also implement equals, hashCode and toString ( ok, they don't have that super call I see). So what is special here? I think they are trying to point out that we can't have equals return true if we compare instances of two different ChronoLocalDate implementations. Would that be it?

But they have isEqual and the compareTo also that lets you compare instances of two different ChronoLocalDate implementations.
Since the isEqual and equals are independent of each other, the isEqual method just seems like a utility method, in that it gives us an option to do an equal type check on different implementations of ChroloLocalDate.

I get the part that they have static factory methods for instantiation.

But overall I don't get what's so special about these value based classes. I mean I get the rules ( I think ), but I think I'm missing something somewhere.
What do you think of these value based classes?


Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38509
    
  23
I think the thing about equals method means they have equals method written strictly following the general contract of equals. And you always use equals rather than ==, except possibly for this first line
The bit about immutable instances means those object fulfil the strict requirements of being immutable, as here and here.
You would not want super.foo() in an immutable class. If the superclass can be subclassed it isn't immutable, so the immutable class would directly extend java.lang.Object, and you would not want super.hashCode() or super.toString(), because they use something similar to the identity hash code.
The isEqual method might take a related class and return whether certain fields are equal. I can imagine GregorianCalendarImmutable would have an isEqual method taking ArabicCalendarImmutable as a parameter type. True if the two dates occur at the same time
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
Campbell Ritchie wrote:I think the thing about equals method means they have equals method written strictly following the general contract of equals. And you always use equals rather than ==, except possibly for this first line


Yeah, since this class extends directly from the Object class and it is a final class, it keeps the equals contract.


Campbell Ritchie wrote:I can imagine GregorianCalendarImmutable would have an isEqual method taking ArabicCalendarImmutable as a parameter type. True if the two dates occur at the same time


I couldn't find those classes. But I get your point. The isEqual will allow us to test instances of two different implementations of ChronoLocalDate ( say JapaneseDate and ThaiBuddhistDate) according to the isEqual implementation in ChronoLocalDate. For the instances of same implementation, the criteria defined in that implementation would apply.

I got these parts. Thanks.

These classes are also going to be thread safe cause they are immutable. So I guess that is all there is to them?
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38509
    
  23
Chan Ag wrote: . . . I couldn't find those classes. . . . I got these parts. Thanks. . . .
That's because those classes only exist in my head

And, “you're welcome”
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

I believe the "final instance" is simply a sloppy wording. I understand it as "an instance of a final class". If the class wasn't final, some child class might make changes (eg. override equals, or add mutable instance variables) which might break the equals contract of the parent class. (Edit: sorry, now I see this was already covered here.)

I personally don't get the reason behind this:
do not have accessible constructors, but are instead instantiated through factory methods which make no committment as to the identity of returned instances;

That the class must not rely on identities was already specified several times. Not having an accessible constructor is an unnecessary requirement. For example, String is clearly a value class, but it has accessible constructors.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Campbell Ritchie wrote:You would not want super.foo() in an immutable class.

May I ask why? I don't see why this would - generally - preclude immutability.

For example, the JodaTime library has immutable classes that extend an abstract parent and even reuse some functionality of the parent class.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
Martin, I think that bit about static factory methods is to prevent having to instantiate a new (and sometimes duplicate ) object every time.

Since the class is immutable, static factory methods might be a nice thing to consider. Also since the value based classes are final already, there is not going to be any requirement to subclass them. So I think static factory methods are not a bad choice for this case.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Yes, I understand the advantages of having factory methods. However, class that has an accessible constructor can still behave well as a value-based class, but not adhering to any other of the requirements mentioned on that page would clearly make problems when trying to use that class a a value-based one. I mean, the "no accessible constructor" should be listed as a recommendation, not a requirement. But I'm probably splitting hairs here.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
<Guessing>
I think that must one of the reasons for coming up with a new name called 'value based classes'. :-) So then the value based classes are not just another word for immutable types. Oh then, String won't be a value based class.
</Guessing>

But perhaps I am just missing some fine aspect that can be derived from all those rules... something that just immutable types didn't solve... I seriously couldn't understand what was so very special about these value based classes that they really considered naming the category differently.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

I've always understood immutable class as nothing more than a final class composed of final instance variables. This already makes the class thread-safe, and therefore very useful. I do have some immutable classes which aren't value-based classes in my projects (I didn't need - and therefore didn't implement - proper equals and hashCode methods in them - yet).

Value-based class adds a well-defined equals and hashCode behavior. So value-based classes are a subset of immutable classes. Generally speaking, these classes will behave well in collections (even as map keys), and, probably even more importantly, with Java 8 streams too, so it is a useful new category to define.

However, if String isn't a value-based class then I don't know what is This is why I questioned using the "no accessible constructor" as one of the defining aspects of the "value-based class".
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
Oh then that must be it.

I didn't realize that an immutable type didn't have to implement equals and hashCode methods to stay immutable. Given the immutable property, it's hard to imagine why an immutable implementation wouldn't implement equals and hashCode methods, so it could treat two meaningfully objects as equal objects. But yeah, the immutable property doesn't state that they have to. So that explains why a formal definition for value based types was must have been necessary.

Yes, having no accessible constructors but just static factory methods makes the specifications sort of restrictive. Probably that explains why there are just two value based classes in the Java standard library as of now ( I'm not sure if there are more ).
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38509
    
  23
You can have immutable objects which are implicitly different from one another. That is how an enum works. You can therefore use the == operator on enum elements secure in the knowledge that it will work correctly. It even says so in the Java Language Specification.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Amazingly, enum need not be immutable. This code compiles and executes as expected (printing values 0 and 10):
Not that it would be particularly useful (except when using enum to implement a Singleton, perhaps).
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38509
    
  23
Never knew you could do that. Agree, I can't see a use for it.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
I knew we could have variables that constituted the state of an enum object. I knew we could have setters for such fields and that we could have other methods that changed their state. But I never for once realized this very thing made them mutable. I always thought they were immutable. And I don't know why. I just sort of assumed them to be one of the immutable types.

Thanks so much, Martin, for removing that misconception.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7713
    
  20

Chan Ag wrote:I knew we could have variables that constituted the state of an enum object. I knew we could have setters for such fields and that we could have other methods that changed their state. But I never for once realized this very thing made them mutable. I always thought they were immutable. And I don't know why. I just sort of assumed them to be one of the immutable types.

And in general they are. I think what Martin is saying is that you can change internals, though (like him) why you'd want to, I have no idea, especially since enums are "sort of" static.

That's a good question for a Monday: Can anyone come up with a good reason for a mutable enum?
I suspect there might be situations where it's useful, particularly if the modification is synchronized (and providing it doesn't have any bearing on "equality"); but can't think of one off the top of my head.

Winston

Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

I've just realized, to my own horror, that I do have a mutable enum in my project! It's an enum which represents certain RMI calls (under the hood the RMI calls are implemented as an overloaded method on the enum), and the enums keeps statistics about calls being made. I can then create reports from these stats. I even have a class which turns the enum into Swing's TableModel.

Updating is done partly by means of AtomicIntegers and partly by synchronization.

Whether it is a good reason, though, that's up to the jury to decide...
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

Having a mutable enum is exactly the same as having mutable singletons. Generally a bad idea, unless you're doing stuff that doesn't relate directly to your business logic (like logging). I would argue that in the latter case, aspect oriented programming is a more elegant solution.

I've never found use for mutable enums, and I doubt I ever will.

I'm troubled that the part that Chan quoted says: "are final and immutable (though may contain references to mutable objects)". This sentence is horribly contradictory.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

I used to have a singleton which provided things like a connection pool for the application to use. So, it was quite mutable. Then I converted it to an enum with one entry, because that's much more straightforward than the old logic for creating a singleton and it's easier to see that there's only one thing. But it's still mutable; and I don't see a problem with that. In fact, I don't see why I should have to make an object immutable just because there happens to be only one object of its type.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

Personally, I'd prefer to get the connection pool through a service loader.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Stephan van Hulst wrote:I'm troubled that the part that Chan quoted says: "are final and immutable (though may contain references to mutable objects)". This sentence is horribly contradictory.

Indeed. I'd say that the sentence is missing some bits about defensive copies of these objects being made.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

Hmm I suppose I should change "horribly contradictory" to "misleading".
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Stephan van Hulst wrote:Personally, I'd prefer to get the connection pool through a service loader.


And the other things? (Like SWT-wrapped browser windows for example.) Personally I don't think that putting in a lot of work to get those things from some other source is a good use of my time, given that I have a perfectly good singleton which will manage them. To me the expectation that a singleton will only manage immutable objects is too far over the top.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

Could you quickly expand on what you mean by an SWT-wrapped browser window, and how/when it's used by the code?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Stephan van Hulst wrote:Could you quickly expand on what you mean by an SWT-wrapped browser window, and how/when it's used by the code?


Sure. It's a web browser component from this site: The DJ Project which uses SWT to incorporate a browser natively into Java code. My code interfaces with the component to run Google Maps Javascript code and select locations from maps. Since it takes quite a while to initialize this component (i.e. longer than you'd want in a GUI application), I create one as the application is starting up.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

Interesting, I'll have to consider this.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Basically my question here is: I have mutable objects, I need one of each to be used by the controller part of my application, so using a singleton to manage those objects seems like a reasonable thing to do. That's why I'm dubious about this "Singletons must be immutable" rule, which I never encountered before.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7713
    
  20

Paul Clapham wrote:Basically my question here is: I have mutable objects, I need one of each to be used by the controller part of my application, so using a singleton to manage those objects seems like a reasonable thing to do. That's why I'm dubious about this "Singletons must be immutable" rule, which I never encountered before.

Interesting discussion. I wonder, however, if something like this couldn't be done with dependency injection. I also find it slightly counter-intuitive to use enums for the sorts of factories issued by service providers, but I certainly understand that it's now the "preferred" method for creating singletons.

Winston
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Dependency injection? Sure, it's always possible to do that. It's just a question of whether you want a design where the initialization code has to know in detail which of the many controller objects need which of the many singleton objects and pass them via parameters, or a design where the controller objects ask for the singleton objects if they need them. In my opinion the latter version is simpler, at least in my case.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
Paul Clapham wrote:Dependency injection? Sure, it's always possible to do that. It's just a question of whether you want a design where the initialization code has to know in detail which of the many controller objects need which of the many singleton objects and pass them via parameters, or a design where the controller objects ask for the singleton objects if they need them. In my opinion the latter version is simpler, at least in my case.


This is interesting. I'm just done studying the command pattern from the Head First Design Patterns book. So it's still fresh in my mind. Isn't the singleton object here playing the part of an invoker ( we could also view it as a manager if the manager essentially does just one thing ) that must manage a set of different mutable objects? So obviously since I am always going to require just one invoker, it makes sense to create it as a singleton. I remember being taught that the best way to implement a singleton is the enum way.

How about we named such an enum to something like MutableSomeEnum so we'd know it's a special mutable enum.

Ok, that was one way of thinking.

Another feeling is this...
What! Synchronizing on an enum ( I haven't even seen that yet )! What if the synchronization is way too expensive!

Then another feeling is this -
But what if I don't require that much of synchronization?

So, argh.. over to the next day. :-) I'm done thinking for today.



Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
So, argh.. over to the next day. :-) I'm done thinking for today.

Not yet, sorry. One more last thing...

Chan Ag wrote:
This is interesting. I'm just done studying the command pattern from the Head First Design Patterns book. So it's still fresh in my mind. Isn't the singleton object here playing the part of an invoker ( we could also view it as a manager if the manager essentially does just one thing ) that must manage a set of different mutable objects? So obviously since I am always going to require just one invoker, it makes sense to create it as a singleton. I remember being taught that the best way to implement a singleton is the enum way.

How about we named such an enum to something like MutableSomeEnum so we'd know it's a special mutable enum.


But couldn't we use an EnumMap with the immutable enum objects as keys and the mutable objects they managed as values?

Edit : Got the EnumMap idea from here.

Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
I remember being taught that the best way to implement a singleton is the enum way.


But I realize that mutability defies the very reason why, if at all they are needed, creating a singleton the enum way is the right way.

I think I will keep to immutable enums only.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Chan Ag wrote:But I realize that mutability defies the very reason why, if at all they are needed, creating a singleton the enum way is the right way.

I don't think so. The enum provides efficient and thread-safe initialization of the singleton instance (and prevents even serialization or other tricks from creating multiple instances). This is unrelated to the question of whether the singleton instance is immutable. Without enum, you'd have to use the double locking or the lazy holder something like that.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
How would it be thread safe if it had a mutable property?

Edit : Granted, you wouldn't need the ugly DCL. But you can't say the same thing about synchronization. Just the thought of having to synchronize on an enum sort of feels like ... a new thing.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
And an another way of looking at how a mutable enum avoids DCL( in select cases ) is this....

Is the mutable property pointing to some not initialized indicator object ( the null object )
If not initialize it...

Let us say this was only for lazy initialization .. So you now need to implement a property freeze mechanism, right?
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Chan Ag wrote:Just the thought of having to synchronize on an enum sort of feels like ... a new thing.

I did synchronization on an enum

In the example I've mentioned above (my mutable enum that keeps the statistics) I synchronize on the enum constant whose statistics I need to update. Enum is a class just like any other, so if you happen to need to prevent concurrent access, synchronizing on it is probably the right thing to do.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1013
    
  15
I think the separation of concerns applies here. A singleton is just a singleton ( one of its kind ). It doesn't have to be immutable ( though, and as we all know that, immutability comes easy with enums ). So if we think of a singleton as a singleton only, it may or may not need synchronization/immutability(and thread safety that comes with it) depending on the context.

Even though we may not require mutable enums often/ever( choose the one you like ), knowing the associated stuff helps.

This discussion has been really interesting and very telling. Thanks, all of you.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: What are Value based classes?