<Foo>从构建器返回 A<List>



在我的代码中,我想使用类型化的参数,比如:

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" )可以),但左手边必须完全原样。

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

通话内容如下:

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

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

根据"注释",我认为您可以更改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:使用org.hamcrest.Matcher代替ArgumentValidator

这就是我所能想到的。如果你能对你的要求更具体一点,那就太好了。

ParameterDefinition是泛型类吗?换句话说,它被定义为吗
public class ParameterDefinition<T>

或者以外的东西

public class ParameterDefintion

如果是,则可以返回ParameterDefintion<List<String>>,但如果不是,则需要决定在<T>区域中放置什么值。

顺便说一句,在静态方法中添加final没有任何效果,而且是多余的。我会把它取下来。

ParameterDefinition获取泛型参数后,您可以编写

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

你甚至不需要的演员阵容

(ParameterDefinition) ParameterDefinition.build( List.class, "names" );

如果您想使用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包含的内容。

最新更新