为什么ByteArrayOutputStream使用int?

时间:2014-01-29 18:37:05

标签: java

也许有人可以帮助我理解,因为我觉得我错过了一些可能影响我的程序运行的东西。

我正在使用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)...

感到困惑

3 个答案:

答案 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被寻址并移动到堆栈(bipushsipush操作码)时,它们就会立即转换为整数。

但有时java实际上使用 257(!)值。当InputStream#read()返回256个值时,但当它没有内容时,它将返回-1值。或者,可以抛出一个EOFException(就像其他一些方法一样),但java中的异常很慢。

即使您不需要-1 OutputStream#write值,但它会减少投射。但是,它也具有误导性。