简体   繁体   中英

How to pass a parameterized class as an argument

My goal is to develop a class that can output an object of a specified class.

public class GetMe<T> {
    public T get() {
        Object obj = generateObject();
        return (T) obj;
    }
}

Now, I know this isn't possible due to erasure. So, we can pass in a class instance and use that to cast.

public class GetMe<T> {
    public GetMe<T>(Class<T> clazz) {
        this.clazz = clazz;
    }

    public T get() {
        Object obj = generateObject();
        return clazz.cast(obj);
    }
}

This works great! As long as the class isn't parameterized. If it is, then I've got a problem.

I'm not allowed to use List<String>.class . If I pass in a ParameterizedType (which in itself is difficult to generate), there's no cast method to use.

Is there a way out of this quagmire?

我认为超级型令牌可以为您解决这个问题。

The problem with List<String> is that, because of erasure, it would at runtime indistinguishable from any other List<?> . The easiest way around this is to create a new class or interface which has the generic part "fixed", like

public interface StringList extends List<String> {
    /* nothing to see here */
}

This way you have a type token (the StringList.class object) which you can pass around at runtime and specifies exactly what you want, but without the need for generics at runtime.

Here is just a small idea. I'm not really sure if it will fit in your context but nevertheless:

public class GetMe<T>
{
    public List<T> getList() {
        @SuppressWarnings("unchecked")
        List<T> result = (List<T>) new LinkedList(); 
        return result;
    }
}

Cheers!

The first problem is how you plan to instantiate a List object. If you disclose more of what you are trying to build, we may be able to help you better.

You may want to use Type instead of Class. Type can represent all generic types, although it's not pleasant to work with.

abstract public class GetMe<T> 
{
    Type type;
    public GetMe<T>(Type type) 
    {
        this.type = type;
    }
}

Another problem is how to create a generic type like List<String> . The "super type token" looks neat in syntax, in reality it's basically

static class XX extends TypeReference<List<String>>{}
....
Type typeListString = Util.extract(XX.class);

I would much prefer this way

List<String> f;

Type typeListString = getDeclaredField("f").getGenericType();

Actually, many of these frameworks that do fancy runtime generic magics are working on instance fields only.

I think the confusion comes from the fact that you're trying to create an object from List<> which in face it an interface, not an object.
So no matter what you'd try, you just can't create an instance of List<> , (interfaces aren't actual classes, and don't have constructors)

Try using a constraint to avoid having interfaces put in the declaration:

public class GetMe<T extends Object> 

This will guarantee that T is an actual class and not an interface.

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