我在循环中有一个方法调用,目前无法编译:
for (Example example : Util.getExample(List.class)) {
// Do something with example
}
的Util:
public class Util {
public <T> T getExample(Class<T> clazz) {
//...
}
}
明显的解决方法是将回复从getExample
强制转换为List<Example>
。我想知道:是否有另一种方法可以避免演员表?
更多信息:
海报要求提供更多信息,所以这里......
我已经构建了一个围绕注释处理的框架,该框架编写代码来访问和改变类成员(构造函数,字段和方法)。该框架支持Parceler和Transfuse,并允许我在编译期间识别属性并生成访问或修改所述属性的代码。对于私有属性(私有构造函数,私有字段,私有方法),我使用实用程序来执行这些操作(Parceler's,Transfuse's)以通过反射来破坏封装。
Parceler具有在序列化期间展开集合的功能,以便序列化给定集合的成员。对于私有集合,InjectionUtil
用于在循环中访问这些属性:
for (Example example : InjectionUtil.getField(List.class, Container.class, container, "exampleField")) {
// ...
}
这是我目前面临的bug,因此,为什么我要求避免演员。我宁愿不投,因为我想在一般情况下生成一些代码来访问类型并尊重Java泛型。
答案 0 :(得分:4)
如果您的getExample
方法应该始终返回列表,那么是,将其返回类型更改为List<T>
。但是,由于您将List.class
作为参数传递,看起来您希望有一个方法可以返回列表和非列表,具体取决于您传递的类对象。
如果是这样,那就不会像你希望的那样工作。在这种情况下,您的方法仅返回原始类型List
。要让它返回List<Example>
,您必须将其传递给假设的List<Example>.class
,但是没有这样的事情。通用类型参数在编译时被擦除,因此List<Example>
和List<String>
实际上都是同一个类;它们没有单独的类对象,因此类对象参数不能告诉您的方法它应该返回什么类型的列表。
您可能需要尝试不同的设计方法。由于这显然是一个简化的示例,如果您发布有关您实际尝试完成的更多详细信息,您可能会获得更多帮助。
答案 1 :(得分:2)
在这种情况下可以使用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
作为参数,这样您仍然可以为它提供一个类。这就是Gson的做法。
答案 2 :(得分:0)
我认为这是一个设计问题......
由于您调用的Util
中的方法被称为getExamples
,因此修复它可能也是合理的,以返回一些集合,其中元素是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;
}
}
例如,如果你想使用List<Example>
来实现ArrayList<E>
,那么你会这样做:
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
框架。