Java Generics:无法正确获取语法

时间:2012-05-23 13:28:00

标签: java generics

我正在尝试编写一个自定义UI组件(在android上),它将显示一个文本编辑控件以及两个可以向上或向下单击的按钮。向上递增编辑控件中的数字,向下递减它。

我希望这个类在数字类型上是通用的,即我想专门用于int和float类型的类。

我一直在阅读这个很好的Java Generics Tutorial,但我的特定实现似乎没有编译。这就是我所拥有的:

public class NumberPicker<T> extends LinearLayout implements OnClickListener,
        OnFocusChangeListener, OnLongClickListener {

    public interface OnChangedListener<T> {
        void onChanged(NumberPicker<T> picker, T oldVal, T newVal);
    }

    public interface Formatter<T> {
        String toString(T value);
    }

    // Error: Cannot make a static reference to the non-static type T
    public static final NumberPicker.Formatter<T> TWO_DIGIT_FORMATTER =
            new NumberPicker.Formatter<T>() {
                public String toString(T value) {
                        // Do something with T value
                }
        };
}

我在TWO_DIGIT_FORMATTER

的声明中遇到以下编译器错误
  

无法对非静态类型T

进行静态引用

有人可以帮我解释一下语法。来自C ++我很了解通用,并且意识到两者之间的一些差异。我只需要语法帮助。

我尝试改为:

        // "Syntax error on token "int", Dimensions expected after this token"
    public static final NumberPicker.Formatter<int> TWO_DIGIT_FORMATTER =
            new NumberPicker.Formatter<int>() {
                public String toString(int value) {
                    return mFmt.toString();
                }
        };

这给出了“令牌上的语法错误”int“,此符号后面的维度”

4 个答案:

答案 0 :(得分:2)

这与语法无关,它与您的类型TNumberPicker实例相关联的事实有关,而您的{{ 1}}是TWO_DIGIT_FORMATTER,因此与static的任何实例无关。因此,没有类型NumberPicker可供其参考。

答案 1 :(得分:1)

T参数属于NumberPicker实例,每个实例可以具有不同的值,因此不能在该类的静态字段中依赖它。

也不能在public interface Formatter<T>中引用它,因为接口成员默认是静态的。

解决此问题的一种方法是:

  1. TWO_DIGIT_FORMATTER,作为常量应该有参数绑定。当你考虑它时,在这种情况下,未绑定的参数并没有多大意义。
  2. Formatter可以拥有自己独立的参数,在将其传递给NumberPicker实例时会进行检查。 (这已在OnChangedListener中隐式完成。)
  3. 所以你的代码将是这样的:

    public class NumberPicker<T>  {
    
        public interface OnChangedListener<Y> { //
            void onChanged(NumberPicker<Y> picker, Y oldVal, Y newVal);
        }
    
        public interface Formatter<X> {
            String toString(X value);
        }
    
        public void setFormatter( Formatter<T> formatter ) { ... }
    
        public static final NumberPicker.Formatter<? extends Number> TWO_DIGIT_FORMATTER =
            new NumberPicker.Formatter<Number>() {
                public String toString(Number value) {
                        // Do something with T value
                }
            };
    
    }
    

    我在接口定义中将T替换为XY以避免混淆。接口的参数与NumberPicker的参数完全分开。通过赋予它们不同的名称,这一点变得很明显。

答案 2 :(得分:0)

您的字段TWO_DIGIT_FORMATTER是一个静态字段,即一个类字段,不属于任何特定实例。另一方面,仅当您引用已将T绑定到具体类型的NumberPicker的特定实例时,才会解析类型参数TT的类型随着不同的实例而变化,所以它自然在类字段上没有意义。您必须从static中删除TWO_DIGIT_FORMATTER限定符,然后您必须通过该类的实例访问它。

答案 3 :(得分:0)

您不能在静态方法中使用泛型。 Generic将对您的实例进行paremetrize,而static不是实例,而是类范围。

您可以将其更改为(删除静态):

public final NumberPicker.Formatter<T> TWO_DIGIT_FORMATTER = ...