如何将参数化类作为参数传递

时间:2011-02-12 19:07:54

标签: java generics

我的目标是开发一个可以输出指定类对象的类。

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

现在,我知道由于擦除,这是不可能的。因此,我们可以传入一个类实例并使用它来进行转换。

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

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

这很棒!只要该类没有参数化。如果是,那我就有问题了。

我不允许使用List<String>.class。如果我传入ParameterizedType(这本身很难生成),则没有cast方法可供使用。

有没有摆脱这个泥潭的方法?

5 个答案:

答案 0 :(得分:5)

我认为super type tokens可能会为您解决此问题。

答案 1 :(得分:2)

List<String>的问题在于,由于擦除,它在运行时与任何其他List<?>无法区分。最简单的方法是创建一个新的类或接口,其通用部分“固定”,如

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

这样你就有了一个类型标记(StringList.class对象),你可以在运行时传递它并准确指定你想要的东西,但不需要在运行时使用泛型。

答案 2 :(得分:1)

这只是一个小想法。我不确定它是否适合你的背景但是:

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

干杯!

答案 3 :(得分:0)

第一个问题是您计划如何实例化List对象。如果您披露了更多您正在尝试构建的内容,我们可能会帮助您做得更好。

您可能希望使用Type而不是Class。类型可以表示所有泛型类型,但使用起来并不愉快。

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

另一个问题是如何创建像List<String>这样的通用类型。 “超类型令牌”在语法上看起来很整洁,实际上它基本上是

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

我更喜欢这种方式

List<String> f;

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

实际上,许多这些花哨的运行时通用魔法的框架只在实例字段上工作。

答案 4 :(得分:0)

我认为这种混淆来自于你试图从List<>创建一个对象,它面对一个接口,而不是一个对象。
所以无论你尝试什么,你都无法创建List<>的实例,(接口不是实际的类,也没有构造函数)

尝试使用约束来避免在声明中放置接口:

public class GetMe<T extends Object> 

这将保证 T 是一个实际的类,而不是一个接口。