cubic lettuce
cubic lettuce

Reputation: 6559

Can the return type of a static generic method depend on its arguments?

I "simply" want to write a static generic method that takes the generic Collection<E> of any type E as its input, and outputs a result of the appropriate type Vector<E>. Since the type E is always known at compile-time, this should not be a problem - but it is... Thus, a call should later look like:

Collection<String> coll = ...
Vector<String> vec = Convert.toVector(coll); // either this or...
Vector<String> vec = Convert<String>.toVector(coll);

Here is what I tried - all without success:

import java.util.Collection;
import java.util.Vector;

public class Convert<E> {

    // 1st try, same type E as class => Error: Cannot make a static reference to the non-static type E
    public static Vector<E> toVector1(Collection<E> coll) {
        return new Vector<E>();
    }

    // 2nd try, a new type X. => Error: X cannot be resolved to a type
    public static Vector<X> toVector2(Collection<X> coll) {
        return new Vector<X>();
    }

    // 3rd try, using wildcard. => Error: Cannot instantiate the type Vector<?> 
    public static Vector<?> toVector3(Collection<?> coll) {
        return new Vector<?>();
    }

    // 4th try, using bounded wildcard. => Error: Cannot make a static reference to the non-static type E
    public static Vector<? extends E> toVector4(Collection<? extends E> coll) {
        return new Vector<E>();
    }
}

Is this not possible at all? And if not, is there a good reason why not? Or am I just doing it wrong? Probably there is some solution using Lambda expressions?

Upvotes: 0

Views: 814

Answers (3)

Konstantin Yovkov
Konstantin Yovkov

Reputation: 62864

// 1st try, same type E as class => Error: Cannot make a static reference to the non-static type E
public static Vector<E> toVector1(Collection<E> coll) {
    return new Vector<E>();
}

This is because you've already defined a type-parameter, called E, on instance context and the compiler doesn't allow you to use it on static context.


// 2nd try, a new type X. => Error: X cannot be resolved to a type
public static Vector<X> toVector2(Collection<X> coll) {
    return new Vector<X>();
}

Here, even though you don't use the instance type-parameter E, but another one, called X, the former is not correctly defined. When introducing method-scoped type-parameters, you have to do:

public static <X> Vector<X> toVector2(Collection<X> coll) {
    return new Vector<X>();
}

// 3rd try, using wildcard. => Error: Cannot instantiate the type Vector<?> 
public static Vector<?> toVector3(Collection<?> coll) {
    return new Vector<?>();
}

The error is simply because the wildcard <?> can be only used in return-types and on initialization, but not on instantiation (like you've done).


// 4th try, using bounded wildcard. => Error: Cannot make a static reference to the non-static type E
public static Vector<? extends E> toVector4(Collection<? extends E> coll) {
    return new Vector<E>();
}

The reason is the same as 1st try. You can fix this by having:

public static <X> Vector<? extends X> toVector4(Collection<? extends X> coll) {
    return new Vector<X>();
}

However, note that when you use this method, you won't be able to add anything but null to the resulting list.

Upvotes: 2

nomis
nomis

Reputation: 2715

From the JDK documentation: "For static generic methods, the type parameter section must appear before the method's return type.". So it should look like

public static <E> Vector<E> toVector1(Collection<E> coll) {
    return new Vector<E>();
}

Upvotes: 3

Eran
Eran

Reputation: 393846

You should give your static method its own generic type parameter :

public static <T> Vector<T> toVector1(Collection<T> coll) {
    return new Vector<T>();
}

You were missing the generic type parameter declaration (<T>) before the return type of the method.

Upvotes: 5

Related Questions