[英]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
的返回值getExample
为List<Example>
。 我想知道:是否有另一种避免演员阵容的方法?
更多信息:
海报要求更多信息,所以这里...
我围绕注释处理构建了一个框架,该框架编写了用于访问和变异类成员(构造函数,字段和方法)的代码。 该框架同时支持Parceler和Transfuse,并允许我在编译期间识别属性并生成代码以访问或修改所述属性。 对于私有属性(私有构造函数,私有字段,私有方法),我使用实用程序执行这些操作( 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.