也许有人可以帮助我理解,因为我觉得我错过了一些可能影响我的程序运行的东西。
我正在使用ByteArrayOutputStream。除非我错过了很多东西,否则这个类的重点是创建一个byte []数组用于其他用途。
但是,BAOS上的“普通”写入函数取int而不是字节(ByteArrayOutputStream.write)。
根据这个(Primitive Data Types)页面,在Java中,int是32位数据类型,而byte是8位数据类型。
如果我写这段代码......
int i = 32;
byte b = i;
我收到有关可能有损转换的警告,需要更改此内容...
int i = 32;
byte b = (byte)i;
我对write(int)...
感到困惑答案 0 :(得分:5)
为了促进0x7F
以上的无符号字节,会发生这种情况。 int将被默默缩小以便写入。事实上,代码does that带有(byte)
演员。
Ingo说:
可能的原因可能是要写入的字节通常是某些操作的结果,这些操作会自动将其操作数转换为int [,就像某些位操作一样。因此,代码将被抛出为强制转换为字节,这不会增加理解。
答案 1 :(得分:4)
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以来就已经有了。不幸的是,如果没有它在整个地方发生重大变化,它现在无法修复。
答案 2 :(得分:0)
这主要是因为 Java虚拟机模型的堆栈讨厌byte
,但喜欢int
。堆栈使用32位插槽,它匹配int
的大小。
然而,您会注意到 java *与byte[]
引用类似*。但那是因为数组的内容存储在堆中(而不是堆栈中)。每当特定byte
被寻址并移动到堆栈(bipush
或sipush
操作码)时,它们就会立即转换为整数。
但有时java实际上使用 257(!)值。当InputStream#read()
返回256个值时,但当它没有内容时,它将返回-1
值。或者,可以抛出一个EOFException
(就像其他一些方法一样),但java中的异常很慢。
即使您不需要-1
的OutputStream#write
值,但它会减少投射。但是,它也具有误导性。