- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Case objects equality problem
Sun, 2011-12-25, 20:18
sealed abstract class OfferingEvent
case object PhaseStarted extends OfferingEvent
val event = PhaseStarted
event equals PhaseStarted
and comparing event with PhaseStarted with equals method should always
return true
Is this correct?
It seems what Scala 2.9.1 case object does not generate equals method
(but case class generate equals method)
So comparing case objects relies using Object.equals method.
public boolean equals(Object obj) {
return (this == obj);
}
Usually this isn't a problem.
Simple Unit test run correctly always.
But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
mixed mode)
equals sometimes fails.
To investigate problem I overridden equals method :
sealed abstract class OfferingEvent
{
val logger = Logger.getLogger("xxxxx")
override def equals(obj: Any): Boolean = {
val result = super.equals(obj)
logger.info("##-- this: " + this.getClass + " hashCode: " +
this.hashCode + " identityHashCode: " +
System.identityHashCode(this) )
logger.info("##-- obj: " + obj.getClass + " hashCode: " +
obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
logger.info("##-- equals : " + result)
result
}
}
And result is :
Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 4657709
Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027
Dec 25, 2011 20:32:08 INFO ##-- equals : false
Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1059528513
Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027
Dec 25, 2011 20:32:08 INFO ##-- equals : false
Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027
Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
-50818394 identityHashCode: 1922540027
Dec 25, 2011 20:32:08 INFO ##-- equals : true
PhaseStarted hashCode is always same, and if equals is overridden like
in case class it should return correct result – true
But identityHashCode returns different reference id-s and it seems ==
uses identityHashCode-s.
I do not use reflection or any other tricky method to create
PhaseStarted objects.
Always simply
val event = PhaseStarted
But under Tomcat PhaseStarted are created at different times and maybe
for some reason new objects are created.
Note – I don't use different servlets either, all happens under same
servlet.
I am confused.
thanks for any help
toivo
Sun, 2011-12-25, 21:31
#2
Re: Case objects equality problem
does it happen in local scope? or do you store a reference somewhere and
compare it to the object later? because a session might have gotten
serialized and deserialized again - no idea what that does to an object
Am 25.12.2011 21:14, schrieb HamsterofDeath:
> maybe the class is loaded by different classloaders? i heard rumors
> about problems resulting from this
>
> Am 25.12.2011 20:18, schrieb toivo a:
>> sealed abstract class OfferingEvent
>> case object PhaseStarted extends OfferingEvent
>>
>> val event = PhaseStarted
>>
>> event equals PhaseStarted
>>
>> and comparing event with PhaseStarted with equals method should always
>> return true
>> Is this correct?
>>
>> It seems what Scala 2.9.1 case object does not generate equals method
>> (but case class generate equals method)
>>
>> So comparing case objects relies using Object.equals method.
>> public boolean equals(Object obj) {
>> return (this == obj);
>> }
>>
>> Usually this isn't a problem.
>> Simple Unit test run correctly always.
>>
>> But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
>> mixed mode)
>> equals sometimes fails.
>>
>> To investigate problem I overridden equals method :
>>
>> sealed abstract class OfferingEvent
>> {
>> val logger = Logger.getLogger("xxxxx")
>>
>> override def equals(obj: Any): Boolean = {
>> val result = super.equals(obj)
>> logger.info("##-- this: " + this.getClass + " hashCode: " +
>> this.hashCode + " identityHashCode: " +
>> System.identityHashCode(this) )
>> logger.info("##-- obj: " + obj.getClass + " hashCode: " +
>> obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
>> logger.info("##-- equals : " + result)
>>
>> result
>> }
>> }
>>
>> And result is :
>>
>> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 4657709
>>
>> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>>
>>
>> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1059528513
>>
>> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>>
>>
>> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
>> -50818394 identityHashCode: 1922540027
>>
>> Dec 25, 2011 20:32:08 INFO ##-- equals : true
>>
>>
>> PhaseStarted hashCode is always same, and if equals is overridden like
>> in case class it should return correct result – true
>> But identityHashCode returns different reference id-s and it seems ==
>> uses identityHashCode-s.
>>
>> I do not use reflection or any other tricky method to create
>> PhaseStarted objects.
>> Always simply
>>
>> val event = PhaseStarted
>>
>> But under Tomcat PhaseStarted are created at different times and maybe
>> for some reason new objects are created.
>> Note – I don't use different servlets either, all happens under same
>> servlet.
>>
>> I am confused.
>>
>> thanks for any help
>> toivo
>>
>>
>>
>
Sun, 2011-12-25, 21:51
#3
Re: Case objects equality problem
No, I don't store references in session and serialization is not used.
But I do use scala Actor.
And actor is singleton and holds events list.
val offerings = new ListBuffer[Offering]
actor listens outside messages and calls processing logic.
Processing logic examines events list and decides what do to next.
Events in list never get deleted or updated, only new events can be
appended.
Because actor process everything sequentially, I hope where is no race
conditions and synchronization is not needed.
Class loaders may be culprit.
But I don't nothing unusual. And it's hard to believe what Tomcat
changes classloaders during lifecycle of simple servlet.
On Dec 25, 10:30 pm, HamsterofDeath wrote:
> does it happen in local scope? or do you store a reference somewhere and
> compare it to the object later? because a session might have gotten
> serialized and deserialized again - no idea what that does to an object
>
> Am 25.12.2011 21:14, schrieb HamsterofDeath:
>
>
>
>
>
>
>
> > maybe the class is loaded by different classloaders? i heard rumors
> > about problems resulting from this
>
> > Am 25.12.2011 20:18, schrieb toivo a:
> >> sealed abstract class OfferingEvent
> >> case object PhaseStarted extends OfferingEvent
>
> >> val event = PhaseStarted
>
> >> event equals PhaseStarted
>
> >> and comparing event with PhaseStarted with equals method should always
> >> return true
> >> Is this correct?
>
> >> It seems what Scala 2.9.1 case object does not generate equals method
> >> (but case class generate equals method)
>
> >> So comparing case objects relies using Object.equals method.
> >> public boolean equals(Object obj) {
> >> return (this == obj);
> >> }
>
> >> Usually this isn't a problem.
> >> Simple Unit test run correctly always.
>
> >> But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
> >> mixed mode)
> >> equals sometimes fails.
>
> >> To investigate problem I overridden equals method :
>
> >> sealed abstract class OfferingEvent
> >> {
> >> val logger = Logger.getLogger("xxxxx")
>
> >> override def equals(obj: Any): Boolean = {
> >> val result = super.equals(obj)
> >> logger.info("##-- this: " + this.getClass + " hashCode: " +
> >> this.hashCode + " identityHashCode: " +
> >> System.identityHashCode(this) )
> >> logger.info("##-- obj: " + obj.getClass + " hashCode: " +
> >> obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
> >> logger.info("##-- equals : " + result)
>
> >> result
> >> }
> >> }
>
> >> And result is :
>
> >> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 4657709
>
> >> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
> >> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1059528513
>
> >> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
> >> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> >> -50818394 identityHashCode: 1922540027
>
> >> Dec 25, 2011 20:32:08 INFO ##-- equals : true
>
> >> PhaseStarted hashCode is always same, and if equals is overridden like
> >> in case class it should return correct result true
> >> But identityHashCode returns different reference id-s and it seems ==
> >> uses identityHashCode-s.
>
> >> I do not use reflection or any other tricky method to create
> >> PhaseStarted objects.
> >> Always simply
>
> >> val event = PhaseStarted
>
> >> But under Tomcat PhaseStarted are created at different times and maybe
> >> for some reason new objects are created.
> >> Note I don't use different servlets either, all happens under same
> >> servlet.
>
> >> I am confused.
>
> >> thanks for any help
> >> toivo
maybe the class is loaded by different classloaders? i heard rumors
about problems resulting from this
Am 25.12.2011 20:18, schrieb toivo a:
> sealed abstract class OfferingEvent
> case object PhaseStarted extends OfferingEvent
>
> val event = PhaseStarted
>
> event equals PhaseStarted
>
> and comparing event with PhaseStarted with equals method should always
> return true
> Is this correct?
>
> It seems what Scala 2.9.1 case object does not generate equals method
> (but case class generate equals method)
>
> So comparing case objects relies using Object.equals method.
> public boolean equals(Object obj) {
> return (this == obj);
> }
>
> Usually this isn't a problem.
> Simple Unit test run correctly always.
>
> But under Tomcat 6 and OpenJDK 64-Bit Server VM (build 1.6.0-b09,
> mixed mode)
> equals sometimes fails.
>
> To investigate problem I overridden equals method :
>
> sealed abstract class OfferingEvent
> {
> val logger = Logger.getLogger("xxxxx")
>
> override def equals(obj: Any): Boolean = {
> val result = super.equals(obj)
> logger.info("##-- this: " + this.getClass + " hashCode: " +
> this.hashCode + " identityHashCode: " +
> System.identityHashCode(this) )
> logger.info("##-- obj: " + obj.getClass + " hashCode: " +
> obj.hashCode + " identityHashCode: " + System.identityHashCode(obj) )
> logger.info("##-- equals : " + result)
>
> result
> }
> }
>
> And result is :
>
> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 4657709
>
> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
>
> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1059528513
>
> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- equals : false
>
>
> Dec 25, 2011 20:32:08 INFO ##-- this: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- obj: class jd.PhaseStarted$ hashCode:
> -50818394 identityHashCode: 1922540027
>
> Dec 25, 2011 20:32:08 INFO ##-- equals : true
>
>
> PhaseStarted hashCode is always same, and if equals is overridden like
> in case class it should return correct result – true
> But identityHashCode returns different reference id-s and it seems ==
> uses identityHashCode-s.
>
> I do not use reflection or any other tricky method to create
> PhaseStarted objects.
> Always simply
>
> val event = PhaseStarted
>
> But under Tomcat PhaseStarted are created at different times and maybe
> for some reason new objects are created.
> Note – I don't use different servlets either, all happens under same
> servlet.
>
> I am confused.
>
> thanks for any help
> toivo
>
>
>