返回A <list <foo>&gt;来自builder </list <foo>

时间:2013-08-16 13:49:46

标签: java generics

在我的代码中,我想使用类似的类型参数:

public static final ParameterDefinition<List<String>> NAMES
    = ParameterDefinition.build( List.class, CURRENCY );

这允许我稍后写:

List<String> names = object.get( NAMES );

没有任何案件。

但它没有编译(ListList<String>不兼容)。

我可以使用以下代码编译代码:

@SuppressWarnings( { "unchecked", "rawtypes" } )
public static final ParameterDefinition<List<String>> NAMES
    = (ParameterDefinition) ParameterDefinition.build( List.class, "names" );

如何摆脱@SuppressWarnings?如何在Java 6中模拟List<String>.class

注意:右侧的代码可能更复杂(即build(List.class, String.class, "names" )可以)但左侧必须完全一样。

4 个答案:

答案 0 :(得分:1)

一种方法可能是引入扩展类/接口的子类型并定义具体的类型参数,例如:像interface StringList extends List<String>这样的东西。在build方法中,您可以获得已传递的类的泛型类型。

电话会是这样的:

public static final ParameterDefinition<? extends List<String>> NAMES = ParameterDefinition.build( StringList.class, CURRENCY  );

是的,这不是很优雅,但可能是一个开始。我会更多地考虑一下这个问题。 :)

答案 1 :(得分:0)

ParameterDefinition是一个通用类吗?换句话说,它被定义为

public class ParameterDefinition<T>

之外的其他内容
public class ParameterDefintion

如果是,那么您可以返回ParameterDefintion<List<String>>,但如果没有,则需要确定<T>区域内的值。

顺便说一下,将final添加到静态方法没有任何效果,并且是多余的。我会将其删除。

在ParameterDefinition获取Generics参数后,您可以编写

    public static final <X> ParameterDefinition<X> build(Class<X> clazz, String name) {
      ...
      return ...;
    }

你甚至不需要你在

的演员阵容
(ParameterDefinition) ParameterDefinition.build( List.class, "names" );

答案 2 :(得分:0)

如果您想使用build(List.class, String.class, "names" ),那么您可以使用public class ParameterDefinition<T extends List<P>, P>作为类定义,这样就可以创建类似ParameterDefinition<List<String>, String> test = new ParameterDefinition<List<String>, String>();的类。

它不漂亮,但应该有效,它允许您定义List包含的内容。

答案 3 :(得分:0)

从“注意”,我带你可以改变build(?)的定义。 您也没有指定ParameterDefinition是否确实需要知道类型。 如果没有,这将解决问题:

public static <X> ParameterDefinition<X> build(String name);

如果你需要参数只是因为Java有时候是愚蠢的猜测泛型类型,但是它没有在方法中使用,你也可以这样做

public static <X> ParameterDefinition<X> build(Class<? super X> type, String name);

如果ParameterDefinition使用type参数来确保值的类型,那么您应该知道没有可能的参数来确保结果实际上是List<String>。这可能是您的问题没有简单解决方案的原因。

如果您不在乎,可以执行以下操作:

public static <X> ParameterDefinition<X> build(Class<X> type, String name) { ... }

@SuppressWarnings({"unchecked", "rawtypes"})
public static <X> Class<List<X>> listOf(Class<X> itemType) {
    return (Class) List.class;
}

static ParameterDefinition<String> = build(String.class, "name");
static ParameterDefinition<List<String>> = build(listOf(String.class), "keywords");

这里的优点是SuppressWarnings在库代码中,API用户不必处理它们。

如果列表的所有元素都是String非常重要,并且我认为您的实现应该是可扩展的,那么您将需要一个更复杂的方法:

public interface ArgumentValidator<X> {

    boolean accept(Object o)

}

public static <X> ArgumentValidator<X> instanceOf(Class<X> type) { ... }

public static <X> ArgumentValidator<List<X>> listOf(Class<X> itemType) { ... }

public static <X> ParameterDefinition<X> build(ArgumentValidator<X> validator, String name) { ... }

public static <X> ParameterDefinition<X> build(Class<X> type, String name) {
    return build(instanceOf(type), name);
}

static ParameterDefinition<String> = build(String.class, "name");
static ParameterDefinition<List<String>> = build(listOf(String.class), "keywords");

Protip:而不是ArgumentValidator,请使用org.hamcrest.Matcher

这就是我所能想到的。如果您能更加具体地了解您的要求,那就太好了。