Java的通用`any`函数

时间:2012-12-03 19:01:29

标签: java generics

我有各种NodeToken和其他类。每个类都有自己的Type枚举。

我有节点列表,令牌列表和其他内容列表。

我经常想查看列表中是否有特定Type的项目。

例如,要查看令牌列表中是否有任何关键字,我会循环遍历它们:

Token found = null;
for(Token token: statement)
    if(token.type == Token.Type.KEYWORD &&
      (token.token.equals("static") ||
      (token.token.equals("final")) {
        found = token;
        break;
    }
if(found != null) {
    ....

如果我写小帮手,我可以整理我的代码(因为我想弄清楚列表中的内容):

Token any(Collection<Token> haystack,Token.Type type,String... needles) {
   for(Token straw: haystack)
       if(straw.type == type)
            for(String needle: needles)
                if(needle.equals(straw.token))
                    return straw;
   return null;
}

然后,在其他地方,我可以:

if((found = any(statement,Token.Type.KEYWORD,"static","final")) != null)
   ...

有没有办法对Node和其他变量进行概括,对于非字符串的比较和字段不同,命名方式不同?

使用C ++模板,您可以使用鸭子类型;使用Java,我很难看到如何做到这一点,虽然使类可以与他们自己的类型相媲美等等可能是一种前进的方式?

2 个答案:

答案 0 :(得分:3)

您将使用duck typing的东西通常可以通过java中的接口来完成。考虑一下这个界面:

public interface Typed<T extends Enum<T>> {
    T getType();
    String getToken();
}

然后,您可以将any方法更改为仅使用实现此接口的类型:

public <A extends Enum<A>, B extends Typed<A>> B any(Collection<B> haystack, A type, String... needles) {
    for (B straw : haystack)
        if (straw.getType().equals(type))
            for (String needle : needles)
                if (needle.equals(straw.getToken()))
                    return straw;
    return null;
}

答案 1 :(得分:1)

您可以在Java中使用鸭子类型反射,但很可能是

  • 更复杂,而不是更简单
  • 更容易出错

我建议你坚持最简单的写作和理解。

FOUND: {
  for(Token token: statement)
    if(token.type == Token.Type.KEYWORD &&
      (token.token.equals("static") ||
      (token.token.equals("final")) {
        // handle token here
        break FOUND;
    }
  // handle not found here
}

而不是使用标签,您可以创建方法并在找到匹配项时返回。

我怀疑KEYWORD检查在这里是多余的,因为我假设你不能拥有staticfinal而且它不是关键字。一种更有效的方法就是这样。

static final List<String> KEYWORDS_TO_MATCH = Arrays.asList("static", "final");

FOUND: {
   for(Token token: statement)
     if(KEYWORDS_TO_MATCH.contains(token.token)) {
        // handle token here
        break FOUND;
     }
   // handle not found here
}