The return type of common methods

If I have a method like

public INode getNode(final int offset);

      

I'm guessing it doesn't add something to make the method return a generic type like:

public <T extends INode> T getNode(final int offset);

      

Or am I missing something? I think the generic return types only matter if one of the parameters is of the same type (or super / subtype)?

+3


source to share


2 answers


public <T extends INode> T getNode(final int offset);

      

Not only does this not provide any additional information for the caller, but it is absolutely dangerous: the only way to implement this method signature is to use an uncontrolled listing, which cannot be type safe since the type parameters of the method are specified by the caller (either explicitly or implicitly through type inference ) and type parameters are not available to implement this method. For example, consider the following program:

class NodeCollection {
    private INode[] nodes = new INode[42];

    public <T extends INode> T getNode(final int offset) {
        return (T) nodes[offset];
    }

    public <T extends INode> setNode(final int offset, T node) {
        nodes[offset] = node;
    }
}

class ANode implements INode {}
class BNode implements INode {
    void foo();
}

public class Test {
    public static void main(String[] args) {
        NodeCollection nc = new NodeCollection();
        nc.setNode(0,new ANode());
        BNode b = nc.getNode(0); // throws ClassCastException (sic!)
    }
}

      

Best Practice: Don't use an unchecked cast unless you are sure it will be correct at runtime.

I think the generic return types only matter if one of the parameters is of the same type (or super / subtype)?

There are more cases, for example:

public <T> T getFavorite(Class<T> clazz) {
    return clazz.cast(favorites.get(clazz));
}

      



or

interface List<E> {
    E get(int index);
}

      

or the examples in Colin's answer where the type variable just appears as a type parameter in the return type, which is acceptable due to type erasure.

Edit

I think there is no way to preserve the type if you want to use the exact type of node (instead of instanceof should precede it)

Of course there is a visitor template .

+4


source


In the example you give it doesn't really add any value, except that the developer of the cast implementation returns a return value (in T

). (If it doesn't have a way to get the value T

, but to do so, it will need to call another method that returns T

, so you just move the casting a little further.

So it's not a good idea when you show us.


There are a few cases where a generic method that applies only to the return value might be useful. For example:

public static <T> Collection<T> generateCollection() {
    return new ArrayList<T>();
}

      

This allows you to create an object Collection

from T

without making any throws.



Or if you want the developer to do the implementation to pass their object (basically works when the specified object uses generics), an example from Collections

:

public static final <T> Set<T> emptySet() {
    return (Set<T>) EMPTY_SET;
}

      


Resources

+1


source







All Articles