因此,我有一些近似的代码(为简洁起见,被截断了-忽略诸如public成员变量之类的东西):

  public class GenericThingy<T> {
    private T mValue;
    public final T[] mCandidates;

    public GenericThingy(T[] pCandidates, T pInitValue) {
      mCandidates = pCandidates;
      mValue = pInitValue;
    }

    public void setValue(T pNewValue) {
      mValue = pNewValue;
    }
  }

  public class GenericThingyWidget {

    private final GenericThingy<?> mThingy;
    private final JComboBox mBox;

    public GenericThingyWidget (GenericThingy<?> pThingy) {
      mThingy = pThingy;
      mBox = new JComboBox(pThingy.mCandidates);
      //do stuff here that makes the box show up
    }

    //this gets called by an external event
    public void applySelectedValue () {
      mThingy.setValue(mBox.getSelectedItem());
    }
  }
}


我的问题是mThingy.setValue(mBox.getSelectedItem());调用会产生以下错误:

类型为setValue(capture#4-of ?)的方法Generics.GenericThingy<capture#4-of ?>不适用于自变量(对象)

我可以通过从GenericThingyWidget的mThingy和pThingy声明中删除<?>来解决此问题-这给我一个“ GenericThingy是原始类型。对GenericThingy的引用应该参数化”警告。

我还尝试将setValue调用替换为

mThingy.setValue(mThingy.mCandidates[mBox.getSelectedIndex()]);


我真正希望它能正常工作,但是产生了非常类似的错误:

类型为setValue(capture#4-of ?)的方法Generics.GenericThingy<capture#4-of ?>不适用于参数(capture#5-of ?)

有什么方法可以在不生成“原始类型”警告(我可以接受的“未经检查的转换”警告)并且不将GenericThingyWidget变成通用类型的情况下进行此操作?我想我可以将mBox.getSelectedItem()的返回值转换为某种值,但是我不知道那是什么。

作为一个额外的问题,为什么对mThingy.setValue的替换调用不起作用?

最佳答案

我看到两种可能性。

GenericThingyWidget的私有添加项中-Goetz's capture helper pattern:

public void applySelectedValue() {
  helper(mThingy, mBox.getSelectedIndex());
}

private static <T> void helper(GenericThingy<T> pThingy, int pIndex) {
  pThingy.setValue(pThingy.mCandidates[pIndex]);
}


或者,又脏又臭,对GenericThingy的API进行了修改:

public void setValue(int value) {
  mValue = mCandidates[value];
}





  作为一个额外的问题,为什么对mThingy.setValue的替换调用不起作用?


Brian Goetz的文章可能比我更好地解释了这一点,但我会尝试一下。

mThingy.setValue(mThingy.mCandidates[mBox.getSelectedIndex()]);


编译器知道mThingy具有某些类型参数,但它不知道该类型是什么,因为它是通配符。它将为此类型创建一个占位符-“ capture#4-of?”。编译器还知道mCandidates具有某种类型,但也不知道它是什么。它创建了全新的“捕获”类型-“捕获#5- of?”尽管您和我可以推断出它们应该是相同的类型,但编译器(至少目前是这样)无法得出这个结论。因此,您收到错误信息。

捕获助手可以解决这个问题。尽管编译器不知道类型是什么,但知道它具有类型,因此它允许您将其传递给helper方法。一旦进入helper方法,就不会有通配符,并且编译器不必对通配符是否真正引用相同类型进行任何推理。

07-24 21:10