如何在通用层次结构中集成非泛型类?

时间:2010-11-18 08:54:42

标签: java generics

对不起标题: - /

我为计算器编写了一个解析器。它有效,但我不喜欢我的令牌层次结构。解析器应该不知道具体的数字类型,例如它应该可以配置为Double,BigDecimal等。所以我有一个通用的令牌接口

public interface Token<T> { }

public class NumToken<T> {
  private final value T;
  ...
} 

public class OperatorToken<T> {
  ... 
} 

现在我的问题是如何处理无论数字类型如何都相同的“结构”标记,例如括号和分隔符。泛型参数不仅在这种情况下无用,它阻止我使用该类型的枚举。但是,枚举非常有用,例如它可以在switch语句中使用。

现在我已经“解决”了这个问题:

public enum CharToken implements Token<Object> {

    OPEN('('),
    CLOSE(')'),
    SEPARATOR(','),
    EOL(';');

    private final char ch;

    private CharToken(char ch) {
       this.ch = ch;
    }
} 

这很有效,但是迫使我在List<Token<? super T>>之类的解析器中编写所有内容,并假设在我转换时所有其他类型实际上都是Token<T>。我明显地使用类型系统来对付谷物:从类型理论的角度来看,我正在撞墙,因为Java在Scala中没有像“Nothing”这样的“底部”类型(这将是一个完美的契合)。有更好的解决方案吗?

[澄清]

T是我的解析器应该处理的预期数字类型,而不是令牌的“内容”。例如。对于OperatorToken<T>,我有一个方法calc(T op1, T op1)。我希望能够通过T对整个解析器进行参数化,因此它使用的所有令牌都需要相同的T(如果你不像我那样欺骗super),那么{{1}不会很有用。

2 个答案:

答案 0 :(得分:1)

JDK中使用的解决方案(例如java.util.Collections.emptyList())正在利用擦除 - 类型参数并不存在,您可能还记得 - 并为方法输入参数推断:

@SuppressWarnings("unchecked")
public enum CharToken implements Token { // Note: No type parameter specified!

    OPEN('('),
    CLOSE(')'),
    SEPARATOR(','),
    EOL(';');

    public static <T> Token<T> open(){ return OPEN; }
    public static <T> Token<T> close(){ return CLOSE; }
    public static <T> Token<T> separator(){ return SEPARATOR; }
    public static <T> Token<T> eol(){ return EOL; }

    private final char ch;

    private CharToken(char ch) {
       this.ch = ch;
    }
} 

// Usage:
Token<BigDecimal> bdOpen = CharToken.open();
Token<Integer> intOpen = CharToken.open();

看起来不是很漂亮,但至少它很容易使用。 (为清洁起见,您可能希望将枚举封装在仅暴露泛型方法的类中。)

答案 1 :(得分:0)

Java中有Void类型,设计用于类似用途。但是,正如Bozho所暗示的那样,IMO的类型参数应该是Character