为什么ByteArrayOutputStream使用int?
也许有人可以帮助我理解,因为我觉得我错过了一些可能会影响我的程序运行的东西。
我正在使用ByteArrayOutputStream。 除非我错过了一些巨大的东西,否则这个类的重点是为其他用途创建一个byte []数组。
但是,BAOS上的“普通”写入函数采用int而不是字节( ByteArrayOutputStream.write )。
根据此( 原始数据类型 )页面,在Java中,int是32位数据类型,字节是8位数据类型。
如果我写这个代码……
int i = 32; byte b = i;
我收到一个关于可能有损转换的警告,需要对此进行更改…
int i = 32; byte b = (byte)i;
我真的很困惑写(int)…
ByteArrayOutputStream
只是覆盖OutputStream
声明的抽象方法。 所以真正的问题是为什么OutputStream.write(int)
以这种方式声明,当它声明的目标是将单个字节写入流时。 流的实现在这里是无关紧要的。
你的直觉是正确的 – 在我看来,这是一个破碎的设计。 是的,它会丢失数据,正如文档中明确指出的那样:
要写入的字节是参数b的八个低位。 b的24个高位被忽略。
在我看来, write(byte)
会更加明智。 唯一的缺点是你不能在没有强制转换的情况下用文字值调用它:
// Write a single byte 0. Works with current code, wouldn't work if the parameter // were byte. stream.write(0);
看起来没问题,但不是 – 因为文字0的类型是int
,它不能隐式转换为byte
。 你必须使用:
// Ugly, but would have been okay with write(byte). stream.write((byte) 0);
对我而言,按照原样设计API并不是一个足够好的理由,但这就是我们所拥有的 – 并且自Java 1.0以来就已经有了。 不幸的是,如果没有它在整个地方发生重大变化,它现在无法修复。
为了促进0x7F
以上的无符号字节,这就发生了。 int将被默默地缩小以便写入。 实际上,代码通过(byte)
强制转换来实现。
正如Ingo所说:
可能的原因可能是要写入的字节通常是某些操作的结果,该操作会自动将其操作数转换为int [,如某些位操作。 因此,代码将被抛出为强制转换为字节,这不会增加理解。
这主要是因为Java虚拟机模型的堆栈讨厌byte
,但喜欢int
。 堆栈使用32位插槽,与int
的大小相匹配。
但是你会注意到java *像byte[]
引用一样 。 但那是因为数组的内容存储在堆(而不是堆栈)中。 每当特定byte
被寻址并移动到堆栈( bipush
或sipush
操作码)时,它们立即转换为整数。
但有时java实际上使用257(!)值。 当InputStream#read()
返回256个值时,但当它没有内容时,它将返回-1
值。 或者,可以抛出一个EOFException
(就像其他一些方法那样),但java中的exception很慢。
即使你不需要OutputStream#write
的-1
值,也OutputStream#write
它是连贯的,它会减少转换。 但是,是的,它也具有误导性。