Question

I'm having trouble figuring out how to properly cast a generic object in java to a type that extends the generic object.

For example, say I some setup like the following:

public class Parameters extends SomeCustomMap<String, String>
{
   ...
}

public class SomeCustomMap<K, V> implements Map<K, V>
{
    public SomeCustomMap<K, V> getSubSet(...)
    {
        SomeCustomMap<K, V> subset;

        ...

        return subset;
    }
}

class ExampleApp
{
    private void someMethod()
    {
        Parameters params;
        Parameters paramsSubSet;

        try
        {
            ...

            paramsSubSet = (Parameters) params.getSubSet(...);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

Running code similar to the above consistently throws a ClassCastException, the likes of which I do not fully understand. Any assitence for how to correctly set up a scenario similar to the above would be appreciated! Namely, how might I properly cast the the SomeCustomMap object that is returned from the params.getSubSet(...) method back to a Parameters object?

Thanks in advance!

Was it helpful?

Solution

You can try something like this:

public <T extends SomeCustomMap<K, V>> T getSubSet(...){
    T subset = (T)this.clone();
    subset.clear();

    return subset;
}

creation looks a little funny - feel free to change it to whatever you want :)

As a bonus you will not need to cast :)

paramsSubSet = params.getSubSet(...)

OTHER TIPS

Your Problem is that the Subset returned by getSubSet is a of instance SomeCustomMap and not of Parameters.

This problem does not deal with generics. You will get the same problem if you did not use generics.

I don't know how you create an instance of subset but maybe you could use the template desing pattern and some generics to fix your problem.

Though I've commented asking for more information, based on what you've posted so far, I think getSubSet is constructing a SomeCustomMap to return (with new SomeCustomMap) somewhere. If you don't override getSubSet in Parameters, then Parameters.getSubset will return a SomeCustomMap (the base class), not a Parameters, so your typecast to Parameters fails.

(Hot tip, if you override getSubSet in the Parameters class, you can change the return type to Parameters and avoid the typecast.)

Generics don't inherently have anything to do with casting (save that due to the nature of erasure, generic parameters cannot be checked during a cast).

If you're getting a ClassCastException in this case, it means that the object returned really is not an instance of Parameters. Just before you cast, try calling

System.out.println(params.getSubSet(...).getClass());

and see what the actual run-time class of the subset is. Chances are the problem lies elsewhere, as your expectation that the subset is a Parameters object is almost certainly not correct at runtime - it's a SomeCustomMap or some other subclass thereof.

As others have explained, the issue is that the actual object you are constructing in getSubSet() is not an instance of Parameters.

Here's one possible workaround. I don't love it, but it is a way to declare the method in SomeCustomMap but have its return value be typed correctly for any subclass.

public static <T extends SomeCustomMap<K, V>> getSubSet(T fullSet)
{
    T subset;

    ... (use fullSet instead of this)

    return subset;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top