【问题标题】:java conditional operator and different typesjava条件运算符和不同的类型
【发布时间】:2014-07-26 05:18:58
【问题描述】:

我在Item 类中有两个方法:

public void setValue(String v);
public void setValue(Double v);

我想在另一个类中使用条件运算符setVAlue

String str = ...
Double dbl = ...
item.setValue((condition) ? str : dbl);

但是编译器说:

cannot find symbol
symbol  : method setValue(java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>)

我认为编译器使用Double 和String 的最近的公共超类(超接口) 作为条件运算符的类型。但为什么呢?

【问题讨论】:

  • 类型必须统一(例如相同)。 Java 选择调用的重载是在期间编译时选取的。

标签: java conditional-operator


【解决方案1】:

因为做任何其他事情都没有任何意义。三元条件运算符必须返回某个特定类型的某个值——所有表达式必须在编译时产生一个特定类型。此外,请注意重载决议也发生在编译时。您在此处尝试调用的行为(后期绑定)在 Java 中的这种形式中不存在。

表达式的类型必须与 truefalse 子表达式兼容。在这种情况下,最近的公共祖先类是 Object,并且您没有 setValue(Object) 重载。

这是以工作方式重写你所拥有的最简单的方法:

if (condition) {
    item.setValue(str);
} else {
    item.setValue(dbl);
}

您还可以提供setValue(Object) 重载,检查传递的对象类型并委托给适当的setValue() 重载,如果类型不可接受则抛出异常。

【讨论】:

  • 是的,是的 +1。我正要回复=/
  • 小提示,它不仅可以编译setValue(Object),还可以编译列出的任何其他类型(setValue(Serializable)setValue(java.lang.Comparable&lt;? extends Object&gt;) 等),但如果提供了多个,则需要进行强制转换以使调用不产生歧义。
  • @vandale 确实,我考虑过添加它,但认为这可能太多了,无法一次全部转储到 OP 上。但我很高兴你确实提到了它。
【解决方案2】:

Java Language Specification

[...]

否则,第二个和第三个操作数的类型为 S1 和 S2 分别。令 T1 为应用拳击产生的类型 转换为 S1,并令 T2 为应用产生的类型 拳击转换为 S2。条件表达式的类型是 将捕获转换 (§5.1.10) 应用到 lub(T1, T2) 的结果。

在您的情况下,让我们将T1 设为String,将T2 设为Double

来自 JLS,关于the least upper bound (lub)

一组引用类型的最小上界或“lub”是 比任何其他共享超类型更具体的共享超类型 (也就是说,没有其他共享超类型是最小上层的子类型 绑定)。

您可以继续阅读 JLS 来练习计算 lub 的确切方式,但从上面的定义中我们可以看到编译器错误消息中提供的内容是有道理的。

请记住,三元运算符用作具有单个值的单个表达式。该值在编译时必须具有类型。因此,JLS 必须为其指定规则。

这是一个相关的问题/答案

【讨论】:

    【解决方案3】:

    如果您想使用三元运算符,则只有以下代码才能解决您的问题。为了进行测试,我将 false 作为默认值,您可以使用条件表达式。

    public class st1 {
        public static void main (String []args) {
            Item i = new Item();
            i.setValue (false?"test":0.0);
        }
    }
    
    class Item {
        private String str;
        private double d;
        public void setValue (Object str) {
            try {
                d = Double.parseDouble (str.toString());
                System.out.printf ("Double type : %f", d);
            } catch (NumberFormatException ne) {
                this.str = str.toString();
                System.out.printf ("String type : %s", this.str);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-02-06
      • 2015-04-06
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多