Technique for extending a class with private const

2019-04-29 11:51发布

问题:

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.

回答1:

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).



回答2:

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.