简体   繁体   English

为什么用int文字初始化新的Long Wrapper是有效的?

[英]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. 在运行时,会发生从intlong扩展的原始转换。

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 + 1int ,即-2147483648int溢出),该int转换为long值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM