Java 为什么ByteArrayOutputStream使用int?
也许有人能帮我理解,因为我觉得我遗漏了一些可能会影响我的程序运行的东西 我正在使用ByteArrayOutputStream。除非我遗漏了一些重要的内容,否则这个类的重点是创建一个byte[]数组以供其他用途 然而,BAOS上的“普通”写函数采用int而不是byte() 根据this()页,在Java中,int是32位数据类型,byte是8位数据类型 如果我写这个代码Java 为什么ByteArrayOutputStream使用int?,java,Java,也许有人能帮我理解,因为我觉得我遗漏了一些可能会影响我的程序运行的东西 我正在使用ByteArrayOutputStream。除非我遗漏了一些重要的内容,否则这个类的重点是创建一个byte[]数组以供其他用途 然而,BAOS上的“普通”写函数采用int而不是byte() 根据this()页,在Java中,int是32位数据类型,byte是8位数据类型 如果我写这个代码 int i = 32; byte b = i; 我得到一个关于可能有损转换的警告,需要对此进行更改 int i = 32; b
int i = 32;
byte b = i;
我得到一个关于可能有损转换的警告,需要对此进行更改
int i = 32;
byte b = (byte)i;
我真的对写入(int)感到困惑。为了方便在
0x7F
上面使用无符号字节,这会发生。int将被静默地缩小以写入。事实上,使用(字节)
强制转换的代码
正如国际非政府组织所说:
一个可能的原因可能是,要写入的字节通常是某些操作的结果,这些操作会自动将其操作数转换为int[,如]某些位操作。因此,代码中充斥着对字节的强制转换,这对理解没有任何帮助
ByteArrayOutputStream
正在重写OutputStream
中声明的抽象方法。所以真正的问题是,当它声明的目标是向流中写入一个字节时,为什么会这样声明。流的实现与此无关
你的直觉是正确的——在我看来,这是一个破碎的设计。是的,它将丢失数据,正如文档中明确指出的:
要写入的字节是参数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的理由,但这正是我们从Java1.0开始就有的东西。不幸的是,如果没有一个突破性的改变,现在就无法修复它。这主要是因为Java虚拟机模型的堆栈讨厌
字节,但喜欢int
堆栈使用32位插槽,与int
的大小相匹配
但是,您会注意到,java*确实*像byte[]
引用。但这是因为数组的内容存储在堆(而不是堆栈)中。每当一个特定的字节
被寻址并移动到堆栈(bipush或sipush
操作码)时,它们会立即转换为整数
但有时java实际上使用257(!)值。当InputStream#read()
返回256个值时,但当它没有内容时,将返回-1
值。或者,也可以抛出一个EOFException
(就像其他一些方法一样),但java中的异常速度很慢
尽管您不需要为
输出流#write
使用-1
值,但它是一致的,并且减少了强制转换。但是,是的,它也是错误的。但是,我们一点也不清楚为什么它不可能是一个字节
参数-调用方可以很容易地进行转换,如果他们想…@JonSkeet Java API中的许多设计决策都是如此,以至于很难找到背后的合理原因。事实上,该方法接受一个int,并在其中进行显式转换。这就是what的事实,但问题是为什么。我同意在这里很难找到原因——但这只是意味着我们不知道所问问题的答案……一个可能的原因可能是,要写入的字节通常是自动将其操作数转换为int
的某个操作的结果。比如一些位操作。因此,代码中到处都是对字节的强制转换,这对理解没有任何帮助。可以说,如果Java是今天发明的,那么最好只在后跟[]时才允许使用byte和short,并保持所有方法签名都没有byte和short。@Ingo:我想说这确实使代码更清晰,因为这表明您只编写了一个字节,而不是整个整数。如果您的计算结果是int
,并且您调用write(value)
,那么不可能立即删除四分之三的潜在数据……请注意,决定这一点的是OutputStream.write
,不是真正的ByteArrayOutputStream
。是的,ByteArrayOutputStream很难做到这一点,但是它的父类却做到了。除了以byte[]
的形式之外,使用byte
数据类型可以说是个坏主意。这同样适用于short
,IMHO。把byte和short看作是一种必要的邪恶,它只适合让您读写奇怪的二进制数据格式。不要使用字节/短变量、方法参数或返回类型。(不,您不会以任何实质性的方式节省空间(除非在罕见的情况下),而且您的代码实际上可能会更慢。)感谢所有的讨论。我很好奇,即使我的大脑有点紧张,但我的动机和避免使用许多其他功能的做法还是有意义的。我正在使用BAS为我自己的内部VM生成自定义字节码,因此我还想确认我没有编写固有的错误。Java中的字节是有符号的,因此如果该方法将byte
作为参数,我们无法执行stream.write(0xFF)
并获得预期的全字节。现在,为什么java不支持无符号字节…@JoshuaTaylor java实际上支持解释整数类型直到i