Java中的整数转字节类型

5
在Java中,我们可以实现以下操作:
byte b = 5;    

但为什么我们不能向一个接受 byte 参数的函数传递相同的参数呢?

myObject.testByte(5);
public void testByte (byte b)
{
  System.out.println("Its byte");
}     

它会给出以下错误提示:
The method testByte(byte) in the type Apple is not applicable for the arguments (int)

PS:可能是一个愚蠢的问题,我认为我需要再次修正我的基础知识。

谢谢。

5个回答

6

在Java中,硬编码的初始化值有点特殊-它们被假定为对您正在初始化的变量类型进行协商。基本上,第一段代码的效果如下:

byte b = (byte) 5;

如果你做了这样的事情...
myObject.testByte((byte) 5);

如果进行了这个转换,你就不会出现错误,但如果没有进行转换,那么5被默认创建为一个int,而不是自动强制转换。


听起来很有说服力。有什么特别的原因吗? - Ajinkya
2
主要是为了方便 - 规范设计者不想为字节文字和数字文字的初始化创建不同的格式,而且由于变量的类型是声明的一部分,很明显你要把它放到什么样的盒子里 - byte b = 5非常清楚地表明5将被放入一个byte中。另一方面,函数调用并不那么清晰 - 比如,如果你的方法只是命名为testFoo呢?testFoo(5)看起来与testFoo(1024)没有任何区别,但后者实际上无法正常工作。 - Amber

6
原因是当你缩小一个基本类型时,必须显式地进行强制转换 - 这样你就承认可能会丢失数据。
举个例子,当转换数字 5 时,没有数据损失,因为该值在 -128...127 字节值范围内,但是考虑到更大的 int 值,比如 300 - 如果你将其转换为字节,则必须舍弃一些位以使其适合8位。
该主题在 这里 中有详细介绍。

谢谢提供链接。为什么在初始化值时进行隐式转换而不是在函数调用中进行?5也在范围内,不会有任何位损失。 - Ajinkya
1
如果(常量)值对于目标类型太大,编译器将抛出错误。然而,这个可以编译通过:byte b = (byte)1000; - Bohemian

4
通常情况下,未经明确转换将int转换为byte是不被允许的。
然而,如果转换是赋值的一部分,并且该值是一个静态已知的常量,适合目标类型,编译器将自动执行转换。
这种特殊行为在JLS的第5.2节中描述。这是一个仅适用于赋值的特殊情况;它不适用于其他上下文中的转换。
现在我想起来,参数的自动缩小可能是为了避免重载冲突问题。如果我有方法#foo(short)#foo(char),那么foo(65)应该调用哪一个就不清楚了。你可以有特殊规则来解决这个问题,但更容易的方法是要求调用者在所有情况下都显式地指定。

谢谢提供的信息。5也是一个已知的常量,那么为什么编译器在函数调用时不将其转换为byte类型? - Ajinkya
自动缩小常量的特殊规则仅适用于赋值转换,但在JLS中没有解释原因。我已更新我的答案以使其更清晰。 - Stuart Cook
那是一个非常好的问题,Ajinkya。JLS似乎表明赋值转换仅在赋值表达式中应用(通过其与第15章的链接),但它确实在初始化期间执行转换,但不在传递参数时执行,即使它是按值传递的。在我看来,语言本可以设计成在这种情况下应用赋值转换,因此要么出于简单起见选择不这样做,要么确实存在某些语义问题。了解这一点将是很好的。 - Ray Toal
@Ray:是的,当你知道为什么会这样时,它变得非常容易。 - Ajinkya
@Stuart 对于重载解析的洞察很好。 (在此之前我已经点赞了,但无论如何都是很好的补充。) - Ray Toal

0

你必须在你的方法testByte中将参数5强制转换为byte类型。Java会特别关注参数的类型。

修改为:

myObject.testByte( (byte) 5);

0

在Java中,整数字面量默认为int类型。在myObject.testByte(5);中,5是一个整数字面量,将被视为int

众所周知,Java是一种严格类型的语言,因此它不允许将int赋值给byte。您需要进行显式类型转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接