我有一个需要转换为整数的long值。当我使用强制转换时,时间整数值给出一个负值,这是不期望的。但是当我在intValue()
中使用Long
方法时,会出现预期结果。
我想知道转换和使用intValue
()方法
投射示例
int days = (int) ((toDate.getTime() - fromDate.getTime()) / (1000 * 60 * 60 * 24));
intValue示例
int days = ((Long) ((toDate.getTime() - fromDate.getTime()) / (1000 * 60 * 60 * 24))).intValue();
编辑:更详细说明示例以显示减值而不会出现溢出,如评论中所示。在转换之前,结果是27.当转换时,值变为-22。但是如果使用intValue方法,结果是27。
代码
System.out.println("nextDeliveryDate = " + nextDeliveryDate);
System.out.println("nextDeliveryDate.getTime() = " + nextDeliveryDate.getTime());
System.out.println("expectedDeliveryDate = " + expectedDeliveryDate);
System.out.println("expectedDeliveryDate.getTime() = " + expectedDeliveryDate.getTime());
System.out.println("nextDeliveryDate.getTime() - expectedDeliveryDate.getTime() = " + (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()));
System.out.println("(nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24) = " + (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24));
System.out.println("((int) (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24)) = " + ((int) (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24)));
System.out.println("((Long) ((nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24))).intValue() = " + ((Long) ((nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24))).intValue());
结果
Info: nextDeliveryDate = Thu May 14 00:00:00 IST 2015
Info: nextDeliveryDate.getTime() = 1431541800000
Info: expectedDeliveryDate = Fri Apr 17 00:00:00 IST 2015
Info: expectedDeliveryDate.getTime() = 1429209000000
Info: nextDeliveryDate.getTime() - expectedDeliveryDate.getTime() = 2332800000
Info: (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24) = 27
Info: ((int) (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24)) = -22
Info: ((Long) ((nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24))).intValue() = 27
答案 0 :(得分:5)
你可能会遇到int溢出。如果toDate.getTime()
和fromDate.getTime()
之间的差异大于2.147 bilion(即Integer.MAX_VALUE
),则无法将其表示为整数,它只会换行并更改达到最低价值 - 例如Integer.MAX_VALUE + 100
会给你带来负面结果。
你应该首先对long进行所有操作,直到你确定它足够小,可以在没有溢出的情况下强制转换为int
。我认为你的例子都是正确的,第一个肯定比另一个更清楚。
另外,请记住像1000 * 60 * 60 * 24
这样的表达式是整数,它们也可能溢出。例如,一个月内的毫秒数为31 * 24 * 3600 * 1000
,但是这样写的它会返回-1616567296
。
编辑:让我解释您在编辑中附加的输出:
Info: nextDeliveryDate.getTime() - expectedDeliveryDate.getTime() = 2332800000
Info: (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24) = 27
Info: ((int) (nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24)) = -22
Info: ((Long) ((nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()) / (1000 * 60 * 60 * 24))).intValue() = 27
我还会将nextDeliveryDate.getTime() - expectedDeliveryDate.getTime()
称为x
。所以我们可以将它声明为long x = 2332800000
(声明int将给出编译错误,因为它太大而无法保存为4个字节)。
在第一行中,您有x / something
,something
是一个int且x很长,因此something
将转换为long,最终结果很长。
在第二行中,您有((int) x) / something
,所以2332800000长整数转换为整数,给出了-1962167296,然后您有-1962167296 / something
。
在你的最后一行中,你有(Long) (x / something)
,这与第一行实际上是相同的。
答案 1 :(得分:4)
我不认为您的结果应该有所不同,因为这是Long.intValue()
方法的作用:
public int intValue() {
return (int)value;
}
在这两行之间你的控制流是不对的。
您可以尝试以下测试:
Calendar now = Calendar.getInstance();
Date fromDate = now.getTime();
now.add(Calendar.YEAR, 10);
Date toDate = now.getTime();
System.out.println("line 0: " + (toDate.getTime() - fromDate.getTime()));
System.out.println("line 1: " + (int)(toDate.getTime() - fromDate.getTime()));
System.out.println("line 2: " + new Long((toDate.getTime() - fromDate.getTime())).intValue());
int days = (int) ((toDate.getTime() - fromDate.getTime()) / (1000 * 60 * 60 * 24));
System.out.println("line 3: " + days);
days = ((Long) ((toDate.getTime() - fromDate.getTime()) / (1000 * 60 * 60 * 24))).intValue();
System.out.println("line 4: " + days);
答案 2 :(得分:2)
没有区别,这段代码
public static void main(String[] args) {
System.out.println((int) (21470000000l));
System.out.println((int) ((Long)21470000000l).intValue());
}
有这个输出:
-4836480
-4836480
因此,您在toDate
和fromDate
中有不同的值。
如果该值超过整数的MAX,则永远不会得到“预期”结果,因为它不适合那里。
答案 3 :(得分:2)
首先,解释一下Java中的转换为int和IntValue()方法之间的区别。
IntValue()是整数类(和其他包装类)中的方法。
IntValue将做的是获取整数并将其作为int
类型返回。
请注意,int
是原始数据类型,Integer
是保存此数据类型的类。它就像一个包装器,因为有些数据结构无法保存原始数据类型。 See this SO question for more info
基本上:
将int转换为Integer称为装箱。
将Integer转换为int称为取消装箱
正如我提出的SO问题所述。
然而,就您的示例而言,由于涉及的类型,这有点不同。不同之处在于,为了准确性,您将所有操作作为Long
数据类型执行,其中包含的数字比int更多,然后仅将其转换为int。所以你的IntValue()方法来自long数据类型Java7 docs mention of it's use。基本上它只是将它从long更改为int,仍然可能导致溢出。
请注意Long
是原始数据类型long
的包装类(其中原始数据类型没有IntValue()方法)
因此,您获得的值的差异可能是因为当您从Long执行简单转换时 - > int原始数据类型,没有溢出。
我建议您使用不会更改的非常大的数字来测试您的代码(与日期,时间不同,每次获取时都不同)
解决溢出问题
您可能也会感兴趣如何安全地将一个long转换为java中的int ,如this SO question中所述,作为处理溢出可能性的替代解决方案。
我建议的另一种方法是先将降低精度(因此你会失去精度)到一个足够安全的值(并且足够精确),然后再将其转换回int以供使用。 / p>
或者,使用 BigIntegers ,它们是不可变的任意精度整数。 see the the documentation on this class和this SO Q&A on how to use it。它肯定会增加代码的复杂性,因为它们是不可变的。
This other SO question提供了很好的解决方案,可以为ints
和longs
中的检测溢出提供更好的方法,我也建议这样做。