繁体   English   中英

泛型在循环中,试图避免强制转换

[英]Generics in loop, trying to avoid a cast

我在当前无法编译的循环中有一个方法调用:

for (Example example : Util.getExample(List.class)) {
    // Do something with example
}

UTIL:

public class Util {
    public <T> T getExample(Class<T> clazz) {
        //...
    }
}

明显的解决方法是将getExample的返回值getExampleList<Example> 我想知道:是否有另一种避免演员阵容的方法?

更多信息:

海报要求更多信息,所以这里...

我围绕注释处理构建了一个框架,该框架编写了用于访问和变异类成员(构造函数,字段和方法)的代码。 该框架同时支持ParcelerTransfuse,并允许我在编译期间识别属性并生成代码以访问或修改所述属性。 对于私有属性(私有构造函数,私有字段,私有方法),我使用实用程序执行这些操作( Parceler的Transfuse的 )以通过反射破坏封装。

Parceler具有在序列化过程中展开集合的功能,以便序列化给定集合的成员。 对于私有集合, InjectionUtil用于在循环内访问以下属性:

for (Example example : InjectionUtil.getField(List.class, Container.class, container, "exampleField")) {
    // ...
}

这是我当前遇到的错误 ,因此,为什么我要询问避免强制转换。 我宁愿不要进行强制转换,因为我想一般地生成一些代码来访问类型并在此过程中尊重Java泛型。

如果应该让您的getExample方法始终返回列表,则可以,将其返回类型更改为List<T> 但是,由于您要传递List.class作为参数,因此您似乎希望拥有一种方法,该方法可以根据传递给它的类对象返回列表和非列表。

如果是这样,那将不会像您希望的那样起作用。 在这种情况下,您的方法仅返回List ,即原始类型。 要使其返回List<Example> ,您必须将其传递给假设的List<Example>.class之类的东西,但没有这样的东西。 泛型类型参数在编译时被擦除,因此List<Example>List<String>实际上都是同一类; 它们没有单独的类对象,因此类对象参数不能告诉您的方法应返回哪种列表。

您可能需要尝试其他设计方法。 由于这显然是一个简化的示例,因此,如果您发布有关您实际要完成的工作的更多详细信息,则可能会获得更多帮助。

在这种情况下可以使用Guava的TypeToken ,因为List<Foo>.class无效。 通过创建匿名类来使用TypeToken。 由于匿名类保留其通用签名,因此可以使用。

for (Example foo : Util.getExample(new TypeToken<List<Example>>() {}) {
    // do stuff
} 

// utils
public <T> T getExample(TypeToken<T> typeToken) {
    Type type = typeToken.getType();
    // get example
}

TypeToken比仅使用Class更具体。 您也可以使用普通的Type作为参数,因此仍可以将其作为Class进行输入。 这就是Gson的做法。

我认为这是一个设计问题...

由于您正在调用的Util的方法称为getExamples因此似乎可以将其固定为返回某些collection(其元素是Example类的实例)也很合理。

getExamples更改为类似的东西是合理的吗?:

class Util {

  public static <C extends Collection<? supper Example>> getExamples(final Supplier<C> factory) {
       final C result = factory.get();
       // here goes the code that adds the examples to the result collection
       // using add or addAll.
       return result;
  } 

}

因此,例如,如果您想使用ArrayList<E>来获取List<Example>来实现,则可以这样做:

List<Example> examples = Util.getExamples(ArrayList<Example>::new);

尝试改为传递返回的集合类对象引用(例如List.class,ArrayList.class),因为getExamples中的代码将很困难(a)弄清楚如何使用反射实例化适当的构造函数结果(如果仅传递List.class之类的接口类对象,这是不可能的),并且(b)将原始类型的返回值转换为以Example类为元素类型的泛型类型。 后者是微不足道的,但是它并不尽如人意,因为它会产生警告。

更直接的是委托使用代码来明确指示如何实例化结果集合。

如果您放弃返回Collection并在getExamples中使用诸如add和addAll之类的方法,那么您也许应该从java流API借用Collectors框架。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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