简体   繁体   中英

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?

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.

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>();
}
// 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM