Java 如何在隐式长到双转换时产生编译错误?

Java 如何在隐式长到双转换时产生编译错误?,java,double,long-integer,Java,Double,Long Integer,当“long”隐式转换为“double”时,有没有办法让Java编译器产生错误,因为这会导致数据丢失 编辑:我不能接受亚历克斯的答案的原因是它违背了我的目的。我想做的是创建一个最小的“functor”API,它不会因为直接支持基元类型而造成垃圾,而不是只支持使用泛型的对象类型。但是为了保持接口的数量少,我希望使用尽可能少的类型。使用double和Object,对于参数和返回值,我支持(几乎)所有类型,而不会造成垃圾,也不会丢失任何数据(boolean不会转换为double,但也不会通过自动装箱造

当“long”隐式转换为“double”时,有没有办法让Java编译器产生错误,因为这会导致数据丢失

编辑:我不能接受亚历克斯的答案的原因是它违背了我的目的。我想做的是创建一个最小的“functor”API,它不会因为直接支持基元类型而造成垃圾,而不是只支持使用泛型的对象类型。但是为了保持接口的数量少,我希望使用尽可能少的类型。使用double和Object,对于参数和返回值,我支持(几乎)所有类型,而不会造成垃圾,也不会丢失任何数据(boolean不会转换为double,但也不会通过自动装箱造成垃圾,AFAIK,所以不显式支持它是可以的)。因为除了boolean和long之外,所有的基元类型都可以安全地隐式转换为double,所以我几乎满足了所有的需求

这就是问题的来源:如果我不在该API中添加长时间的显式支持,如何防止长时间使用,因为这会导致bug?当然,使用java.lang.Double而不是Double会导致垃圾,从而使API毫无意义


在有人问我之前,我想说我想在实时Android游戏中使用API,因为与JVM不同,“垃圾”是一个真正的问题。

不,这是不可能的。根据Java语言规范,
long
double
被认为是一种扩展转换。它从不触发编译或运行时错误

尽管可能会出现精度损失的情况,但基本体转换的范围仍在扩大 决不会导致运行时异常(§11.1.1)


困难,需要一些研究

第一个想法-字节码

您可以使用字节码操作。可能会找到一些类似于l2d(从长到双)的代码

可能与注释结合使用

制作您自己的注释以抑制此检查的处理。 进行注释处理

第二个想法-JavaME

JavaMe可能会完全禁止使用double

第三个想法-Java解析和数据分析


Java编译器工具包。

如另一个答案中所述,隐式转换不可能产生错误。如果开销可以接受,可以通过将变量或方法参数声明为
java.lang.Double
,使用自动装箱转换强制执行显式检查;编译器将以静默方式对原语
值进行装箱,但会对
表达式引发编译异常

public class Doubles {

  static double asDouble(Double d) {
    return d.doubleValue();
  }

  public static void main(String[] args) {
    long l = Long.MAX_VALUE;
    double d = Double.MAX_VALUE;
    System.out.println(d + " " + asDouble(d));
    System.out.println(l + " " + asDouble(l)); // Compile error.
  }
}

当然,这种方法也有局限性——它不会发现现有代码中的问题。但是,战略性地使用它可以在代码的重要领域提供一些安全性,避免丢失精确性。

@dasblinkenlight:我认为这就是问题所在。请注意,
(双)长.MAX_值
9.223372036854776E18
9223372036854776000
),而
长.MAX_值
9223372036854775807
。由于IEEE-754双精度数字的不完美性质,数据已经丢失。(这不是挖苦他们,他们非常有用,但这里有数据丢失。)@T.J.Crowder你是对的,那里有数据丢失。然而,JLS明确承认“无声”精度损失的可能性。@dasblinkenlight:是的,你对以下问题的回答是正确的(当然)。我只是觉得最初的链接/评论给人的印象是没有数据丢失,所以我想我应该标记发生的丢失。我会等一两天,然后接受你的回答,以防有编译器/Maven/Ant-plugin已经检查过了。基本上,任何错误都可以解决问题,即使它不是来自编译器本身。@SebastienDiot如果任何工具都有它,它可能是IntelliJ。他们有一个令人印象深刻的代码分析设置集合,看看他们提供的检查是否有精度损失。在没有任何“已知的现有解决方案”的情况下,虽然我可以用我自己的编译器插件检查它,但我会选择你的答案为最“正确”。我认为只有最后一个想法有帮助。我假设,尽管我不确定,“double d=1L”编译成与“double d=(double)1L”相同的代码。也就是说,我怀疑一旦有了字节码,就无法区分隐式转换和显式转换。第二个想法与我想要的完全相反;我想使用double,但不是long。更具体地说,我想允许从long到double的显式转换,假设程序员知道他们在做什么,但只标记隐式转换,这可能不是有意的。@SebastienDiot但知道他在做什么的程序员也不会编写显式转换(也)-他知道它是隐式强制转换的,那么他为什么要编写显式强制转换?@Durandal我的意思是,如果我在隐式强制转换中出错,我知道我的长“fits in a double”(不使用超过52位),我想将long作为double传递,而不是java.lang.long对象,以防止垃圾产生,然后我将使用和显式cast to double,告诉编译器这不是错误,不应标记为错误。当然,只有当我在隐式转换中出现错误时,才显式地将long转换为double是有意义的,而到目前为止,情况并非如此。如果将
double
全部替换为
BigDecimal
,这会不会更具定性?不再
10*0.2!=2.0
。(取决于double的用法,是的,BigDecimal是一个PITA。)有趣的想法。它“字面上”解决了我的问题,但不是我的“目的”。我将编辑我的问题以澄清。