1

我有一个泛型类,其方法调用另一个需要类对象作为其参数之一的方法。我希望能够使用在对象创建时设置为泛型的类类型,但我似乎不太能正确理解语法。这是我想做的事情:

public abstract class GenericClass<T> {

    private void doStuff() {
        //do a bunch of stuff

        //This method's signature is methodToCall(Serializable s) and is not a method I can change
        methodToCall(T);
        methodToCall(Class<T>);
        methodToCall(T.class);

        //do some more stuff
    }

}

public class NonGenericClass extends GenericClass<DesiredClass> {

}

Class 对象类型是可序列化的,因此可以这样工作:

methodToCall(DesiredClass.class);

但是我不能轻易地重写该方法,因为我最终只是复制了所有代码,因为方法中间需要类类型。

这是迄今为止我想出的最好的:

public abstract class GenericClass<T> {

    protected abstract void doStuff();

    protected <T> void doStuff(Class<T> cls) {
        methodToCall(cls);
    }

}

public class NonGenericClass extends GenericClass<DesiredClass> {

    @Override
    protected void doStuff() {
        doStuff(DesiredClass.class);
    }

}

这行得通,但感觉泛型类正在浪费它所拥有的关于 T 是什么的知识。methodToCall我首先列出的 3 个调用版本中是否存在语法错误?这是不能做的事情吗?

希望这一切都有意义。

4

3 回答 3

2

如果您正在调用其参数实现任何类型的方法,那么您必须确保您的泛型类型,T实现/扩展该类型。

public class GenericClass<T extends Serializable>
{
    // ...
}
于 2012-10-11T15:09:07.617 回答
2

GenericClass需要一个运行时类型令牌Class<T>传递给其构造函数并保存在字段中的对象。该代码与您的最佳尝试大致一样冗长,但更标准:

class GenericClass<T> {

    Class<T> clazz;

    public GenericClass(Class<T> c) {
        clazz = c;
    }

    protected void doStuff() {
        methodToCall(clazz);
    }

}
于 2012-10-11T15:21:51.563 回答
0

在这种情况下,如果您知道对象的实际运行时类总是要用GenericClass实际类作为类型参数来实现,那么您可以从类的元数据中检索该类型参数(这里我们假设实际类是 的直接子类GenericClass,以简化搜索):

private void doStuff() {
    Class<T> clazz = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    methodToCall(clazz);
}
于 2012-10-12T01:45:22.637 回答