5

Is there a standard technique to "extend" a class with private constructors, as with most Singleton classes? Specifcally, I'm trying to extend the java.lang.management.ThreadInfo class because I'm adding a LOT of them to a HashSet to control uniqueness. However, the way I determine if two threads are equal is different and not identical to the default implementation of the equals() method.

Extending the class is obviously not an option in this case.

Would it be reasonable to make something like a wrapper class which accepts a ThreadInfo in the constructor and then manually populates all relevant fields with the values, then overrides equals() and hashCode(), or is there a better way to do this?

Something like this is what I'm starting to write, but a better implementation would be ideal:

class ThreadInfoWrapper {

    private ThreadInfo info;
    ThreadInfoWrapper(ThreadInfo info) {
        this.info = info;
    }

    //Populate instance variables with Thread.State, thread ID, etc.. with
    //Getters/setters and all that other stuff

    public boolean equals(Object o) { //Unique implementation
    }

    public int hashCode() { //Whatever implementation
    }

}

But this feels like a very roundabout way to achieve some basic functionality. I looked into it, and implementations of Sets with custom Comparators do not exist in the Java standard library. I suppose I could write my own hash set implementation but that's too much work for a simple situation. Any insights would be helpful.

Kon
  • 10,702
  • 6
  • 41
  • 58
  • I'm pretty sure such classes cannot be extended. – Jakob Weisblat Oct 01 '13 at 02:26
  • @JakobWeisblat Actually, they CAN be extended, but only by their inner classes which is not helpful in this situation. I understand that extending them in my own class file will not work. I'm looking for reasonable alternatives and specifically to see if there are any standard practices. I could not find any after searching for a bit. – Kon Oct 01 '13 at 02:30
  • You should not override the equals() method unless you intend to honor its contract. – scottb Oct 01 '13 at 03:51
  • @scottb My override will honor the contract. – Kon Oct 01 '13 at 04:52
  • 1
    See also http://stackoverflow.com/questions/5204082/is-it-possible-in-java-make-something-like-comparator-but-for-implementing-custo – Raedwald Oct 01 '13 at 07:40

2 Answers2

2

By extended, you mean how to create derived classes, which make use of the private constructor as their super class constructor. You can't, they were made private to prevent you doing that. As the JRE classes were written by competent programmers, there will be good reasons for this. So even if you could work around it using trickery, such as reflection or bytecode manipulation, you should not do so.

But all is not lost. You should anyway prefer composition to inheritance. The Decorator and Proxy design patterns can be useful (your example is close to these).

Raedwald
  • 46,613
  • 43
  • 151
  • 237
1

I think what you are doing is reasonable given that there are few other options.

An alternative might be to write your own subclass of HashMap that uses your "special" equals instead of the default. (There may already be apache or guava implementations to do this - anybody know offhand?)

(added later)

Because I'm lazy, and because ThreadInfo has all getters so it's fairly "safe" to expose, I'd be tempted to make the wrapper class very simple, with no getters nor setters:

public class ThreadInfoWrapper {

// public so an outsider can get at the wrapped ThreadInfo 
// could be private if you are sure that will never be necessary
public final ThreadInfo threadInfo;

public ThreadInfoWrapper(ThreadInfo threadInfo) {
  this.threadInfo = threadInfo;
}

public boolean equals(Object o) { //Unique implementation
  // refer to threadInfo.blah...
}

public int hashCode() { //Whatever implementation
  // refer to threadInfo.blah...
}

}

However, this depends on just what info you are using for your equals and hashcode.

user949300
  • 15,364
  • 7
  • 35
  • 66
  • Thanks for the response. When I was searching, I found this response (http://stackoverflow.com/questions/14880450/java-hashset-with-a-custom-equality-criteria) claiming that Guava had "specifically rejected" having any implementation of a Set with equality criteria incompatible with the `equals()` method. – Kon Oct 01 '13 at 02:53
  • Sounds like you have done your research. Good luck. – user949300 Oct 01 '13 at 06:31