Java 泛型 - 类型必须来自 Class T "or" extend S

Java Generics - Type must be from Class T "or" extend S

我正在开发一个 ComboBox(更多的是为了上下文而不是实际意义),我想知道 Java 泛型中是否存在“或”运算符。现在,声明看起来像这样:

public class SComboBox<T extends ComboBoxItem> extends JPanel {

其中 ComboBoxItem 是我为可以在 ComboBox 中使用的项目创建的界面。但是,我也想接受 String 作为一种类型,这似乎是一项艰巨的任务,因为:

  1. Stringfinal class 所以没有人可以扩展它。
  2. 我不确定你是否可以输入类似“|”的内容(or) 运算符,或者直接指定可接受的 class。由于 一个“与”运算符 (<T extends A & B>),所以我认为也可以使用“或”(|)。

我的问题本质上是第 2 点。我可以在泛型中指定 class 我想接受 and/or 使用类似“|”的东西吗?如果没有,是否有任何解决方法或者我应该放弃使用泛型的想法?

泛型没有“或”运算符,原因很简单。

在开头说明类型的想法是允许您在 class.

的实现中使用该类型的 方法

当您使用“与”运算符 (extends A & B) 时,您知道无论传递给您什么对象,您都可以访问 A class 的任何方法以及任何 B class 的方法。

但是如果是“或”会怎样呢?然后向您传递一个对象,该对象可以是 ComboBoxItem 允许您使用 ComboBoxItem 的方法,或者它只是一个字符串,这意味着您不能使用任何此类方法。在编译时,你不知道你传递的是哪个对象,所以给出类型没有意义。

“或”没有帮助。如果您没有使用该对象的任何方法,您也可以根本不使用 extends


这里真正的问题是您正在尝试做什么,它可以应用于字符串和组合框项目,但不适用于其他任何东西。闻起来像是设计问题。

简而言之,这是不可能的。 class 无法从两个接口之一继承,因为无法确定实际实现了哪个 class。

您可以像 JayC667 提到的那样实现一个字符串包装器,并让它实现您的 ComboBoxItem 接口。 我假设您无论如何都需要 ComboBoxItem 引入的一些特殊功能。

一些例子:

interface ComboBoxItem{

    String getDisplayText();

    default Color getBgColor(){
        return Color.WHITE;
    }
    
    default Color getFgColor(){
        return Color.BLACK;
    }

    default ImageIcon getIcon(){
        return null;
    }

    default boolean useIcon(){
        return false;
    }
}

并且通过一个只接受字符串输入的简单实现。

public class StringCbItem implements ComboBoxItem {
    private final String text;

    StringCbItem (String text){
        this.text = text;
    }

    @Override
    String getDisplayText(){
        return text;
    }
}

对于 ComboBox,我可能只使用默认的 JComboBox。 您可以通过传递自定义 ListCellRenderer 实现来覆盖其显示和呈现行为。

public class MyRenderer extends JLabel implements ListCellRenderer<ComboBoxItem> {
     public MyRenderer () {
         setOpaque(true);
     }

     public Component getListCellRendererComponent(JList<?> list,
                                                   ComboBoxItem value,
                                                   int index,
                                                   boolean isSelected,
                                                   boolean cellHasFocus) {

         setText(value.getDisplayText());

         setBackground(value.getBgColor());
         setForeground(value.getFgColor());

         if(value.useIcon()){
             setIcon(value.getIcon());
         }

         return this;
     }
 }

这只是如何操作的一些示例,仅作为起点!
您可以在这里进一步阅读:
How to Use Combo Boxes
Interface ListCellRenderer