由三元运算符产生的意外types
我试图写一个方法得到一个double ,validation数字是否有点后面的东西,如果它返回一个double ,如果不返回一个int 。 
 public class Solution { public static void main(String[] args) { double d = 3.000000000; System.out.println(convert1(d)); System.out.println(convert2(d)); } static Object convert1(double d) { if(d % 1 == 0) return (int) d; else return d; } static Object convert2(double d) { return ((d%1) == 0) ? ((int) (d)) : d; } } 
输出:
 3 3.0 
 所以,我想要的东西发生在方法convert1() ,但不会在方法convert2()发生。 看来这些方法必须做同样的工作。 但是我做错了什么? 
正如其他答案所述,这种行为是因为三元expression式的可能结果必须具有相同的types。
 因此,为了使三元版本的工作方式与convert1()将int转换为Object相同,您需要做的就是: 
 static Object convert2(double d) { return ((d % 1) == 0) ? ((Object) (int) (d)) : d; } 
您看到的效果与此问题中的效果类似。
  Java处理三元运算符types的方式与使用if语句的方式略有不同。 
具体来说, 标准说 :
条件expression式的types如下确定:
…
否则,如果第二个和第三个操作数具有可转换types(§5.1.8)为数字types,则有以下几种情况:
…
否则,对操作数types应用二进制数字提升(第5.6.2节),并且条件expression式的types是第二个和第三个操作数的提升types。
翻到标准页面, 我们看到 :
如果其中一个操作数的types是double,另一个则转换为double。
 这是在这里发生的事情,然后是自动复制到一个Double 。  if语句似乎没有发生这种转换,解释了这种差异。 
 更广泛地说—这不是一个好主意。 我不认为这是一个好的devise来返回一个int或一个double取决于值 – 如果你想四舍五入,使用Math.floor ,如果你不想打印小数,使用printf 。 
 编辑:我不认为这是一个好主意做hacky的东西来规避数字转换系统。 这是一个想法,直接给你一个String ,这似乎是你想要的: 
 static String convert3(double d) { return ((d % 1 == 0) ? Integer.toString((int)d) : Double.toString(d)); } 
 三元运算符要求两个结果值是相同的types,所以int进行自动(安全)加宽转换,以使其double 。 
三元和“等值”不完全一样。
用点号后的数字来解决问题:
 public Object convert(double number){ double whole = Math.floor(number); if(Math.abs(whole - number) < DELTA){ return (int) number; } return number; } 
  DELTA是足够小的常量,用浮点格式编码整数来解决这个问题。 
我从内存中编写代码,但是我认为它背后的想法很明显。