aspose file tools*
The moose likes Java in General and the fly likes making a mostly anonymous Comparator be Serializable Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "making a mostly anonymous Comparator be Serializable" Watch "making a mostly anonymous Comparator be Serializable" New topic
Author

making a mostly anonymous Comparator be Serializable

Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

I've got a NotSerializableException that is coming from my code. Its from a Comparator used in a TreeSet when I try to Serialize the TreeSet. I can't figure out to how to declare the Comparator object as Serializable.

Code snippet:


Any tips or pointers, fixed code, etc. greatly appreciated.
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61437
    
  67

transient


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Bear Bibeault wrote:transient


as in:



??
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61437
    
  67

That should flag it as not part of the persistent state.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

My JDK really doesn't like that. Assorted errors depending on where i put the "transient" word.

transient Comparator<T> comp = new Comparator<T>()

or

Comparator<T> transient comp = new Comparator<T>()

or any other place I can guess to put it.

Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61437
    
  67

Wait. Is this an instance variable?

If not, it shouldn't play a part in serialization to begin with.

(Disclaimer: I am not Dr. Serialization.)
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

The Comparator used for the TreeSet, which is an instance variable.

I don't want to make the TreeSet itself transient.

Is anyone Dr Serialization? Or even deeper, does anyone really grok "transient" and "volatile"?
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
I would think you just need to abandon the idea of doing this in one step with an anonymous class. Just introduce a new named class or interface that extends or implements the two interfaces you need. It can be a local inner class, if you want - should work the same:

I replaced T with Foo because it looks like you're assuming that the class has a method getAgedCount(). That means you have to supply the name of whatever class/interface declares that method - for the code above, I assumed it was Foo. Using T here is too generic.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Mike Simmons wrote:I would think you just need to abandon the idea of doing this in one step with an anonymous class.


That is what I'm doing right now, until Dr Serialization chimes in.

Don't worry about T, its all bound far above, so that all T have the appropriate methods.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
I'm not sure what you expect Dr. Serialization to do, then - this seems straightforward. If you want to serialize a TreeSet with a particular comparator, that comparator needs to be serializable just like everything else in the TreeSet. Unless you're extending TreeSet itself, which seems more complex than you need. Anonymous classes simply do not have any mechanism for implementing two different interfaces. You need another named class.

Alternately, you could try serializing the toArray() of the TreeSet, and then after you deserialize the array, put it back in a TreeSet with an identical comparator. Which, again, seems like more work. Once you have to put code for that comparator in more than one place, it makes more sense to use a new named class for it, I think.
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

Have you read the javadoc of the exception?? When you are serializing objects then the objects (and its instance variables) must implement the java.io.Serializable interface.
Because of the lack of code I'm assuming that the comparator is an instance variable. Which I don't understand because it holds no data end therefor it's not logical to serialize it. You can mark
it as static or as suggested as transient (not in a method).

But if you really want to serialize the comparator then you could do something like this:


Btw your code is never going to compile because T, which is in your case just an object, does not have the method getAgedCount. I think your looking for:


"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." --- Martin Fowler
Please correct my English.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Mike Simmons wrote:I'm not sure what you expect Dr. Serialization to do, then - this seems straightforward. If you want to serialize a TreeSet with a particular comparator, that comparator needs to be serializable just like everything else in the TreeSet.


I'm just trying to not have a separate file for a Comparator class that has one function that is two lines long.

I was hoping for a tweak to the inline declaration that would make things be happy. I could make it an in the file internal class, but even that is overkill. Its two lines of code.

Of course, with Closures in Java 1.9, the problem will be solved with 30 lines decorated with tons of ugly special characters.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Wouter Oet wrote:Btw your code is never going to compile because T, which is in your case just an object, does not have the method getAgedCount.

As I responded up thread, T is properly bound, I just left all that junk out to make the posting shorter.
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

Sorry. Guess I read over that. But do you get it now?
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Pat Farrell wrote:I'm just trying to not have a separate file for a Comparator class that has one function that is two lines long.

Are you talking about .java files or .class files? You don't need another .java file, and the source I posted is only one line longer than what you originally tried, no? If you're talking .class files, well you'll get an extra class file from an anonymous class too.

Pat Farrell wrote:I was hoping for a tweak to the inline declaration that would make things be happy. I could make it an in the file internal class, but even that is overkill. Its two lines of code.

I'm not seeing where it's overkill. This may be a toe-MAY-toe vs toe-MAH-toe thing, though.

Pat Farrell wrote:Of course, with Closures in Java 1.9, the problem will be solved with 30 lines decorated with tons of ugly special characters.

It sounds like the closures in JDK 1.8 will be somewhat simpler than that. Though they're still working on the details; there's no authoritative statement on what they'll look like. If you missed the latest news on this, here is a good starting point.

Still, the fundamental problem here is that you're trying to implement two interfaces at once. I don't think I've seen a closures proposal that addresses this particular use case. Possibly because it's so easy to address it simply by adding another named class or named interface.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4659
    
    5

Mike Simmons wrote:I'm not seeing where it's overkill. This may be a toe-MAY-toe vs toe-MAH-toe thing, though.

It is for sure.

As a style thing, I've learned to really like the way Google Collections encourages you to put the code right with its usage. No one outside the call to the constructor of the TreeSet will ever care about it Comparator, so having it right where its used is a Good Thing for me. YMMV of course.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Pat Farrell wrote:As a style thing, I've learned to really like the way Google Collections encourages you to put the code right with its usage. No one outside the call to the constructor of the TreeSet will ever care about it Comparator, so having it right where its used is a Good Thing for me. YMMV of course.

Well, I like that too, and think it's a worthwhile stylistic goal. But if I have to violate it a little bit in order to handle a rare corner case (when was the last time any of us needed to implement two interfaces simultaneously in an anonymous class?), it doesn't seem like a big deal to me. The code only takes one more line, and the class declaration is right next to the place where it's used. The scope of the class is confined to the method where it's instantiated. That's not quite as nice as confining it to the statement where it's instantiated, but I can live with that. I prefer short methods anyway.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19723
    
  20

I agree with Mike here. Your comparator needs to implement two different interfaces, and that is simply not possible with anonymous classes. Instead of using an inner class Mike chose to use a method-local class. This means it also gets defined to just the method, but the only differences with an anonymous class are:
- it needs a name
- you can use it everywhere in the method
- you can make it extend one class and/or implement any number of interfaces

Both always create a .class file, although the anonymous class file name will be OuterClass$1.class (or any other number) instead of OutherClass$1MethodLocalClass.class (or any other number).


@Bear: using transient will not work in this case since the Comparator is a member field of the TreeSet, and you can't change that.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Rob Prime wrote:Instead of using an inner class Mike chose to use a method-local class.

Well, I would say (and the JLS seems to agree) that a local class is an inner class. That's why I used the term "local inner class". I guess you mean it's not a member class.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19723
    
  20

I'm not sure. You got me doubting the terminology I used, so I checked the JLS.

Section 8.1.3 says
An inner class is a nested class that is not explicitly or implicitly declared static.

Of course I then check out what a nested class is, and the answer is at the top of section 8:
A nested class is any class whose declaration occurs within the body of another class or interface. A top level class is a class that is not a nested class.

That of course leaves the definition of "within the body". Does that include inside methods or initializers? I really don't know, but I interpret this line as "no". So that leaves the following class types:
- top level classes
- method local classes
- anonymous classes
- nested classes
-- static nested classes
-- inner classes (a.k.a. non-static nested classes)
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
JLS 14.3 Local Class Declarations

A local class is a nested class (§8) that is not a member of any class and that has a name. All local classes are inner classes (§8.1.3).

So that leaves the following class types:

- top level classes
- nested classes
-- static member classes (static nested classes)
-- inner classes
--- member classes (non-static)
--- local classes
--- anonymous classes
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

You might define an interface someplace that extends both Comparator<T> and Serializable, and then your anonymous class could implement SerializableComparator...


[Jess in Action][AskingGoodQuestions]
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3018
    
  10
Yeah - I alluded to that in my first post above, saying you need a new named class or named interface that extends or implements Serializable and Comparator. I only gave an example for a class, but the interface version is about the same amount of work, I think.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19723
    
  20

Mike Simmons wrote:
JLS 14.3 Local Class Declarations

A local class is a nested class (§8) that is not a member of any class and that has a name. All local classes are inner classes (§8.1.3).

So that leaves the following class types:

- top level classes
- nested classes
-- static member classes (static nested classes)
-- inner classes
--- member classes (non-static)
--- local classes
--- anonymous classes

I only looked in section 8 so I missed that. I yield
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: making a mostly anonymous Comparator be Serializable