[英]Why initialization of new Long Wrapper with int literal is valid?
Looking at the Java Doc for Long, it only has two constructors: 查看Java Doc for Long,它只有两个构造函数:
1) primitive long as param --> new Long(10L);
2) String as param --> new Long("23");
But this works new Long(23); 但这适用于新的Long(23);
But if the literal is more than the int MAX VALUE (2147483647), the L suffix becomes mandatory so this: ( new Long(2147483648) will now require an L after the value 但是,如果字面值大于int MAX VALUE(2147483647),则必须使用L后缀,这样:(new Long(2147483648)现在将在值后要求L
However: new Long(Integer.MAX_VALUE + 1) is OK 但是:new Long(Integer.MAX_VALUE + 1)可以
Who can explain this? 谁能解释这个?
The first part of your question is straightforward: passing int
where long
is required is allowed because any number that can be represented as an int
can also be represented as a long
. 你问题的第一部分是简单的:通过int
其中long
需要的是允许的,因为这可以表示为一个任意数量的int
也可以表示为一个long
。 This is a so-called widening conversion . 这就是所谓的扩大转换 。
The second part, about new Long(Integer.MAX_VALUE + 1)
, is trickier. 关于new Long(Integer.MAX_VALUE + 1)
的第二部分比较棘手。 Although the widening conversion occurs here as well, it is not of the value that one might think: if you run this program 尽管这里也会发生扩大的转换,但它可能没有想到的价值:如果运行此程序
Long x = new Long(Integer.MAX_VALUE + 1);
System.out.println(x);
you get -2147483648
, not the expected 2147483648
, because of int
overflowing on addition ( demo ). 您会得到-2147483648
,而不是预期的2147483648
,因为int
在加法( demo )上溢出。
The compiler is not smart enough to promote parts of the expression to long
before performing addition. 编译器不够聪明,无法在执行加法之前 long
将表达式的各个部分提升。 Widening conversion occurs after the addition has been performed, on the result of the addition with an overflow. 加法完成后,加法结果发生溢出转换。
You can find the answer in javadocs : 您可以在javadocs中找到答案:
A widening primitive conversion from an integral type to another integral type, or from float to double in a strictfp expression (§15.4), does not lose any information at all; 将原始类型从整数类型扩展为另一整数类型,或在strictfp表达式中将其从float转换为double(第15.4节)根本不会丢失任何信息。 the numeric value is preserved exactly. 数值将精确保留。
The integer value 23
can be converted to long 23L
without loss of any information at all. 可以将整数值23
转换为long 23L
而完全不会丢失任何信息。 Thus with the use of through widening primitive conversions , JVM implicitly converts it to 23L
. 因此,通过使用通过扩展原语转换 ,JVM将其隐式转换为23L
。
So when you call 所以当你打电话
new Long(23)
It becomes 它成为了
new Long(23L)
When we write new Long(23)
, you can think of it as something like the following happening : 当我们编写new Long(23)
,您可以将其视为类似于以下情况的事情:
int i = 23;
long l = i; // widening primitive conversion
Long newLong = new Long(l);
Widening conversions are allowed as per the JLS 5.1.2 , so there are no issues with it. 根据JLS 5.1.2允许加宽转换,因此没有问题。
When we try instead , new Long(2147483648)
, the first step itself fails, as the value is more than what can fit in an int
当我们尝试改用new Long(2147483648)
,第一步本身将失败,因为该值大于int
可以容纳的值
int i = 2147483648; // doesn't fit in int
When we try new Long(Integer.MAX_VALUE + 1)
, you can think of it as something like the following happening: 当我们尝试new Long(Integer.MAX_VALUE + 1)
,您可以将其视为发生以下情况:
int i = Integer.MAX_VALUE + 1; // This gives the INTEGER.MIN_VALUE -2147483648
long l = i ; // widening primitive conversion
Long newLong = new Long(l);
So, this is allowed. 因此,这是允许的。 Hope this helps. 希望这可以帮助。
The differences come from using literal or not. 区别在于是否使用文字。
By using a literal, 通过使用文字,
long1 = new Long(2147483648)
The code will not compile as the compiler checks the validity of the literal again the type of the variable that receives the literal value and 2147483648
is out of range for an int
. 代码不会编译,因为编译器会再次检查文字的有效性,即接收文字值的变量的类型,并且2147483648
超出int
的范围。
So the compiler emits an error. 因此,编译器发出错误。
It is valid for any literal. 它对任何文字均有效。
As the compiler expects to have a specific type as value of the literals , so it does the check : 由于编译器期望具有特定类型作为文字的值 ,因此它进行检查:
The type of a literal is determined as follows: 文字的类型确定如下:
The type of an integer literal (§3.10.1) that ends with L or l is long (§4.2.1). 以L或l结尾的整数文字(§3.10.1)的类型很长(§4.2.1)。
The type of any other integer literal is int (§4.2.1). 任何其他整数文字的类型为int(第4.2.1节)。
... ...
By using a computation : 通过计算:
long1 = new Long(Integer.MAX_VALUE + 1);
the compiler doesn't check if the size of the Long
argument constructor is in the int
range. 编译器不会检查Long
参数构造函数的大小是否在int
范围内。
It is not a literal declaration. 它不是文字声明。
At runtime, an int
to long
widening primitive conversion occurs. 在运行时,会发生从int
到long
扩展的原始转换。
It produces so a int
with Integer.MAX_VALUE + 1
that is -2147483648
(overflow of int
) that is converted to a long
value. 它产生一个带有Integer.MAX_VALUE + 1
的int
,即-2147483648
( int
溢出),该int
转换为long
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.