tags:

views:

123

answers:

2

If I have a base class such that

public abstract class XMLSubscription <T extends XMLMessage>

Is it possible to write a method in XMLSubscription that returns a class object of T?

The only possible solution that I came up with is to have each descendant of XMLSubscription have a method like:

public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage>
{
   public Class <XMLStatusMessage> getExpectedMessageType()
   {     
     return XMLStatusMessage.class;
   }
}
+4  A: 

Unfortunately - and yes, this is due to type erasure - there is no way to return the Class object without providing it at runtime somehow.

Fortunately this is not usually too difficult. Here's how I've typically done this / seen it done:

public abstract class XMLSubscription <T extends XMLMessage> {
    private Class<T> messageType;

    protected XMLSubscription(Class<T> messageType) {
        this.messageType = messageType;
    }

    public Class<T> getExpectedMessageType() {
        return this.messageType;
    }
}

public class XMLStatusSubscription extends XMLSubscription<XMLStatusMessage> {

    public XMLStatusSubscription() {
        super(XMLStatusMessage.class);
    }
}
Greg Case
Fantastic! Your solution saves me a bit of code, and a lot of documentation/explanation! Nice work-around!
A: 

As you guessed, T is erased by the compiler. When you instantiate the object it has no idea that's it's supposed to deal with XMLStatusMessage objects. Your base class would define the following template method, and 1.5's covariant return types would keep the compiler happy with the concrete subclasses:

public Class<T> getExpectedMessageType()

There is one meta-comment: this looks a lot like procedural code, where something calls getExpectedMessageType() and then takes action based on the return type. This might be better implemented using a Visitor pattern, with the visitor implementing "doSomething" methods for each of the subclasses of XMLMessage.

kdgregory
To frame the question I had to cut out a lot of code and actually move stuff around. The actual code does implement a Visitor pattern like you recommend. The type is actually being passed into a Castor method so that it knows how to unmarshal to a Java object.