将静态最终短线转换为短线的原因?
Posted
技术标签:
【中文标题】将静态最终短线转换为短线的原因?【英文标题】:Reason for casting a static final short to a short? 【发布时间】:2015-06-26 10:24:08 【问题描述】:我遇到了一些我之前没有完全理解的东西,想知道是否有人能够解释它。
有一个包含许多静态最终变量的类文件,然后它们的大小写与声明中的类型相同,我想知道为什么。
作为一个例子,我们有:
public static final short A_CONST_VALUE = (short)12;
谢谢。
【问题讨论】:
乍一看完全多余。我怀疑它生成的字节码与将其取出时会产生不同的字节码。 可以参考本帖***.com/questions/769963/… 你知道为什么我们把 F 放在 float 上,把 L 放在 long 上。我认为同样的原因 @Jorge_B 看起来确实很奇怪,我想知道是否还有其他原因。数字范围从 1 到 650 左右,但是……我不知道,只是看起来很奇怪。 对于这个值你不需要强制转换——至少在最近的 Java 版本中是这样。 Java 8 语言规范中描述了这些规则 - 请参阅 Assignment Contexts。 【参考方案1】:这是多余的。
可能是为了清楚起见而添加的,但在我看来,它并没有增加任何价值。
根据JLS § 3.10.1,不带后缀L
或l
的整数字面量属于int
:
如果整数文字以 ASCII 字母
L
或l
(ell) 为后缀,则其类型为long
;否则它的类型是int
因此,将int
转换为short
需要进行缩小转换。但是,根据JLS § 5.2,这样的转换是隐式的:
此外,如果表达式是 byte、short、char 或 int 类型的常量表达式(第 15.28 节):
如果变量的类型是byte
、short
或char
,并且常量表达式的值可以在变量的类型中表示,则可以使用缩小原语转换。
由于 12 可以在 short
类型中表示,因此转换是隐式的。
所以不,强制转换是不必要的,我认为无论有没有强制转换都会生成相同的字节码,尽管我没有对此进行测试。
【讨论】:
【参考方案2】:虽然short
和int
都是整数原始类型,但它们仍然不一样,并且您的文字 (12
) 默认解释为int
。
short
(primitive) 是一个 16 位有符号二进制补码整数,可以存储包含范围 [-215, 215-1] 的值;
int
(primitive) 是一个 32 位有符号二进制补码整数,可以存储包含范围 [-231, 231-1] 的值.
如您所见,int
可以存储范围比short
更大的值,这意味着short
不足以存储来自int
的所有值。
因此,无论何时执行narrowing primitive conversion,编译器都会执行以下两项之一:
-
它会隐式地为您进行转换,在幕后,IFF 文字值可以适合它所转换到的目标类型的范围。
它将要求您显式转换类型 IFF 文字值超出了您希望转换到的目标类型的范围。为什么?因为,当文字值超出目标范围时,编译器不确定您希望将值转换为哪种特定类型..也许您想将其转换为
short
.. 可能转换为 byte
.. 所以是你谁必须告诉编译器。
short a = 32767;
//integer literal 32767 will be automatically converted/casted into "short"
short b = 32768;
//Does NOT compile, as 32768 exceeds "short" range and you need to be explicit, about in which type you want it to be casted, because maybe you want to cast it into the "byte", and not into "short"
byte c = (byte) 32768; //compiles, yet overflows the "byte" type
理解这一点重要:
整数类型 byte、short、int 和 long 的值是从 创建的int 字面量。
所以,无论何时:
long a = 45;
byte b = 2;
short c = 44;
隐式转换适用,并且如果编译器看到文字值超出目标类型的范围,则无法应用转换(代码不会编译),您想使用该类型的变量来存储文字值。
P。 S. 在您的示例中,显式转换在语义上是多余的,尽管有些人可能会发现它对语法可读性很好。
【讨论】:
【参考方案3】:这一行没有问题public static final short A_CONST_VALUE = (short)12;
或public static final short A_CONST_VALUE = 12;
如果您指定的文字在 short
的范围内,即 -32,768 到 32,767。
因此,如果您是这一行 public static final short A_CONST_VALUE = 32768;
并进行编译,您将收到错误“可能丢失精度:int,必需:short”,但如果您编写 public static final short A_CONST_VALUE = (short)32768;
,则 A_CONST_VALUE 的值将被强制转换为 short
,它是值将是 -32768 即它会循环回来。
所以只要字面量在 short 范围内,我们就不需要那种类型转换。此外,我们分配给 A_CONST_VALUE 的字面量不是任何数据类型,它只是一个数值,它应该在范围内 - 32,768 到 32,767,因为 A_CONST_VALUE 是短数据类型。 Nuts n bolts of primitive datatype in java
【讨论】:
是的,但为什么会这样呢?我想这是由相当优秀的开发人员编写的,然后维护了很多年。 未来在超过short值的情况下打样显得有些极端。 能否请您详细说明“但为什么会这样”,因为如果您能帮助我理解您的疑问,我可能会有所帮助 好吧,我想我主要是想了解包括演员在内的思考过程或背后的推理。在所有情况下(除了淫秽的未来证明),它似乎都没有意义。 上述转换是不必要的。对我来说,因为值 12 可以存储在两个字节中(因为 short 是 16 位),所以不需要显式类型转换。当我们写 int a = 20; 时需要它;【参考方案4】:你问为什么有人会这样做:
public static final short A_CONST_VALUE = (short)12;
好吧,我不能代表这样做的人,但这是不必要的。
让我们解开这个:
public static final
修饰符与此无关。
将short
分配给short
不需要强制转换。
但是...文字 1
是一个整数文字,它的类型是 int
而不是 short
。 (如果是1L
,那么它的类型就是long
。)。
通常,将较大类型分配给较小类型(例如int
-> short
)确实需要类型转换来执行原始缩小转换。
但是对于赋值上下文有一个特殊的规则:
如果变量的类型是byte
、char
或short
AND 分配的值是byte
、char
、short
或int
类型的常量表达式 的值
并且该值在变量类型的范围内......
然后执行隐式基元缩小转换。
在简单的语言中,编译器知道赋值不是有损的,并且在没有你指示的情况下进行转换。
Java Language Spec的相关部分是JLS 5.2 ...开头“另外,如果表达式是常量表达式...”
【讨论】:
以上是关于将静态最终短线转换为短线的原因?的主要内容,如果未能解决你的问题,请参考以下文章