【问题标题】:Incompatible types in ternary conditional operator三元条件运算符中的不兼容类型
【发布时间】:2016-01-24 04:43:47
【问题描述】:

我正在尝试根据特定条件为下拉框设置自定义渲染器:

themeComboBox.setRenderer(
    settings == null ? themeComboBox.getRenderer() : new ThemeNameRenderer());

其中themeComboBoxjavax.swing.JComboBox<Path> 的实例,ThemeNameRenderer 是扩展DefaultListCellRenderer 的自定义类。

这不能编译,出现以下错误

method setRenderer in class JComboBox<E> cannot be applied to given types;
    themeComboBox.setRenderer(settings == null ? themeComboBox.getRenderer() : new ThemeNameRenderer());
  required: ListCellRenderer<? super Path>
  found: ListCellRenderer<CAP#1>
  reason: actual argument ListCellRenderer<CAP#1> cannot be converted to ListCellRenderer<? super Path> by method invocation conversion
  where E is a type-variable:
    E extends Object declared in class JComboBox
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ? extends Object

如何使用条件运算符完成这项工作?


  • 我不能用 if 语句或类似语句包围对 setRenderer 的调用,因为我正在通过 NetBeans GUI 编辑器自定义代码。事实上,我需要这样做的全部原因是 ThemeNameRenderer 使用了在编辑器中设计 GUI 时不应加载的依赖项。

  • 我的目标是 Java 1.7。我认为代码确实可以在 Java 1.8 上编译。

  • 我发现以下代码确实有效,但我想尽可能避免使用额外的方法。

    themeComboBox.setRenderer(pickRenderer());
    
    private ListCellRenderer<? super Path> pickRenderer() {
        if (settings == null) {
            return themeComboBox.getRenderer();
        } else {
            return new ThemeNameRenderer();
        }
    }
    

【问题讨论】:

  • themeComboBox.setRenderer((ListCellRenderer&lt;? super Path&gt;) ((settings == null) ? themeComboBox.getRenderer() : new ThemeNameRenderer())); 尝试类型转换
  • 我认为您必须将参数转换为适当的类型。试试settings == null ? (ListCellRenderer&lt;? super Path&gt;) themeComboBox.getRenderer() : (ListCellRenderer&lt;? super Path&gt;) new ThemeNameRenderer());。您可能不需要两个演员表。
  • @PaulBoddington 我试过了,但是没用。
  • @AnkitDeshpande 啊,这就是关键!我尝试按照 Paul 的建议同时提出两个论点,但不是全部。
  • 三元运算符有时会在 java 中出现意外行为。你可以搜索一下,stackoverflow也有一些问题。

标签: java generics java-7 conditional-operator


【解决方案1】:

似乎他们在 Java 8 中为类型推断添加了一些改进,这可能解释了行为上的差异。

检查此页面中的“目标类型”部分:

https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

什么是目标类型的概念已扩展为包括方法参数

这段代码在我使用 Java 1.7 时编译得很好(需要添加强制转换):

themeComboBox.setRenderer(
            (ListCellRenderer<? super Path>) (settings == null ? themeComboBox.getRenderer() : new ThemeNameRenderer()));

您的原始代码使用 Java 1.8 编译得很好:

themeComboBox.setRenderer(
            settings == null ? themeComboBox.getRenderer() : new ThemeNameRenderer());

【讨论】:

  • 你说得对,这行得通!你知道为什么在 Java 1.7 下它是必要的吗?
猜你喜欢
  • 2015-07-02
  • 2015-09-11
  • 2012-01-22
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2011-12-17
相关资源
最近更新 更多