JavaSwing-如何使用泛型在Swing组件上创建UTIL类

JavaSwing-如何使用泛型在Swing组件上创建UTIL类,java,swing,generics,java-7,Java,Swing,Generics,Java 7,我有一个Utils类,以便: public static void setComboBoxDefaultWidth(JComboBox cb) { cb.setPrototypeDisplayValue("mmmmmmmmmmmmmmmmmmmmmmmmmm"); } 问题是,这会导致编译器警告: JComboBox是一种原始类型。对泛型类型JComboBox的引用应参数化 我不确定如何参数化泛型,以便调用方法和函数都能工作(没有编译器错误)。我可以解决一个问题,但不能同时解决两个问题

我有一个Utils类,以便:

public static void setComboBoxDefaultWidth(JComboBox cb)
{
    cb.setPrototypeDisplayValue("mmmmmmmmmmmmmmmmmmmmmmmmmm");
}
问题是,这会导致编译器警告:

JComboBox是一种原始类型。对泛型类型JComboBox的引用应参数化


我不确定如何参数化泛型,以便调用方法和函数都能工作(没有编译器错误)。我可以解决一个问题,但不能同时解决两个问题…

如果您的
JComboBox
s始终包含字符串,则语法为:

public static void setComboBoxDefaultWidth(JComboBox<String> cb)
{
    cb.setPrototypeDisplayValue("mmmmmmmmmmmmmmmmmmmmmmmmmm");
}
publicstaticvoid setComboBoxDefaultWidth(jComboxCB)
{
cb.setPrototypeDisplayValue(“mmmmmmmmmmmmmmmmmm”);
}

事实上,
JComboBox
在Java6中不是通用的,但它在7中成为通用的,只是因为设计有缺陷(因为
getItemAt()
返回了一个对象类型,您必须手动强制转换它)

该方法声明为

public void setPrototypeDisplayValue(E prototypeDisplayValue)
这意味着您必须拥有特定类的特定实例才能调用它,并且类型必须与为组合框声明的类型相对应:

public void setComboBoxDefaultWidth(JComboBox<String> cb) {
  cb.setPrototypeDisplayValue("mmmmmmmmmmmmmmmmmmmmmmmmmm");
}

语法
字面意思是未知类型,参数实际上是未知类型项的
JComboBox

原型显示值必须与键入JComboBox的类型相同

给定一个
JComboBox
,只有知道类型时,才能调用方法
setPrototypeDisplayValue(E prototypeDisplayValue)
。因此,使用通配符(?)不是一个选项。目前,您所能做的就是:

public static void setComboBoxDefaultWidth(JComboBox<String> cb) {
    cb.setPrototypeDisplayValue("mmmmmmmmmmmmmmmmmmmmmmmmmm");
}
publicstaticvoid setComboBoxDefaultWidth(jComboxCB){
cb.setPrototypeDisplayValue(“mmmmmmmmmmmmmmmmmm”);
}
您可以选择的另一个选项是:

public static <E> void setComboBoxDefaultWidth(JComboBox<E> cb, E prototypeValue) {
    cb.setPrototypeDisplayValue(prototypeValue);
}
publicstaticvoid setComboBoxDefaultWidth(jComboxCB,E原型值){
cb.setPrototypeDisplayValue(prototypeValue);
}

但是这是毫无意义的。

如果您想为任何类型的泛型保留JComboBox,您就不能这样做。

您可以使用类似于
public static void setComboBoxDefaultWidth(jComboxCB)
@MadProgrammer的东西,因为它仍然是“未知的”因此,您无法调用setPrototypeValue。@GuillaumePolet您是对的(当然),您没有意识到,
setPrototypeDisplayValue
使用了
@MadProgrammer,它的键入没有意义,这就是为什么我们不会认为它是键入的;-)这是错误的!setPrototypeDisplayValue也被参数化。如果使用“?”通配符,就不能调用setPrototypeValue!它需要是一个已知类型才能调用该方法。抱歉,我真的没有注意到setLightWeightPopupEnabled有一个泛型参数。我只是相信它需要一个字符串,因为它与一个有效的GUI布局相关(想想看,实际上不需要传递E,一个字符串就足够了,因为它只是一个原型)。这实际上强制你在某些情况下生成一个虚拟对象,所以我不喜欢它的设计;在大多数情况下,它是无用的,至少在现实生活中是这样。至于原型值,这就是它的设计方式,实际上是正常的。您只考虑渲染标签/字符串,但组合框可以用于渲染任何内容,而不仅仅是字符串。可能是一个图标,一个复杂的组件,等等。。。在这种情况下,传递字符串是没有意义的。通过传递相同的对象,可以重用渲染器并保证显示的一致性。您也不能设置任何原型值,这就是我所做的。是的,从来没有设置过原型值,但在大多数情况下我仍然在JSE6中工作,所以我从来没有想过它中的泛型。只是有一天随机注意到他们切换到了泛型。只有当combobox模型实际包含大量条目(超过1000条)和/或执行相当复杂的渲染时,设置prototype值才有用。这样做的唯一目的是通过避免渲染组合框的每个值来确定组合框的首选大小来提高性能。因此,在几乎所有情况下,这看起来都是过早的优化。这是错误的!setPrototypeDisplayValue也被参数化。如果使用“?”通配符,就不能调用setPrototypeValue!它需要是一个已知类型才能调用该方法。@mKorbel我不确定从您的评论和您指向我的链接中我应该理解什么。无论如何,如果你尝试杰克的答案,你会立即发现它不起作用。使用“?”意味着:您有一个只包含给定类型的JComboBox,但我不知道是哪一种类型。所以它可以包含整数,布尔值,字符串。。。例如,如果它包含整数,那么调用setPrototypeValue(“mmmmmmmmm”)将大错特错。最终,类型化ListCellRenderer可能会抛出一个ClassCastException:“字符串不能转换为整数”。我认为Swing JComponents的泛型实现是不正确的,我可以查看模型的简单实现,但rest(继承和嵌套)没有被触及…,无法为Sun API给出复杂的答案:-),因为我没有尝试过比较,所以请检查JavaFX+1中ComboBox的API,以扩展此处的其余答案+1-并借此机会对ui中泛型的一般无用性大加指责;-)它在模型领域很好,但在其他任何地方都不行。所有与视图相关的构建块都不关心:渲染器必须是super-E(aka:take-everything,反映在默认渲染器中,也就是说,编辑器根本没有键入)。prototypeValue仅供不关心的渲染器使用。。所以打字完全是胡说八道。。。
public static <E> void setComboBoxDefaultWidth(JComboBox<E> cb, E prototypeValue) {
    cb.setPrototypeDisplayValue(prototypeValue);
}