【问题标题】:Why cast an int to byte in BufferedOutputStream write method that takes an int argument?为什么在采用 int 参数的 BufferedOutputStream 写入方法中将 int 转换为 byte?
【发布时间】:2014-10-15 19:01:31
【问题描述】:

在“Java 编程简介”第 9 版,作者 Y. Daniel Liang,在第 19 章关于二进制 IO 中写了一个代码示例,其中 write() 方法将一个 int 转换为一个字节。为什么?

例如:

    /*
     *  Read and write bytes.
     */
    int intByte = 0;

    int numberOfBytesCopied = 0;

    while( (intByte = bufferedInputStream.read()) != -1){

        bufferedOutputStream.write((byte)intByte);

        numberOfBytesCopied ++;
    }

Java Documentation表示三种重载的写方法:一个是字节数组,另一个是字节数组(允许指定起点和终点),另一个是int。

为什么上面的文本将intByte 转换为一个字节?通过进行该演员表,我看不到需要单个字节的write 方法吗?既然程序运行没有错误,那么 int-cast-to-a-byte 是否被 JVM 重铸为 int?还是JVM将孤独的字节转换为具有单个元素的数组以满足write参数?或者?

我对示例进行了编码,并在有演员表和不演员表的情况下运行它,两者都运行时没有发生任何事故。所以我很想取消演员阵容,但我不明白这是有原因的。

【问题讨论】:

  • 如果您复制的流包含值 >127 会怎样?
  • 您指向的文档回答了我认为的问题:he byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.
  • 啊。因此,即使write 的参数是一个 int,即 4 个字节,也只会写入该 int 的最低字节。所以演员表有点多余,因为无论如何只考虑最低 8 位。所以“在某种程度上”write(int) 方法实际上是在寻找一个 8 位参数,并不关心它是 int 还是 byte。
  • @rossstudtman 我仍然不是 100% 相信此代码在与 >127 字节一起使用时可以正常工作。 (int)((byte)255) 不应该评估为 -1 而不是 255?
  • @biziclop 我不太明白;我正在读取的文件是一个文本文件(从技术上讲,也许阅读器会更准确?) - 我承认,对于被读取为字节的字符,我有点模糊。以我有限的理解,UTF-8 最多可以写入 3 个字节,但 ASCII 使用单个字节(畏缩)?如果我写了一个使用所有 3 个字节的疯狂字符,那么通过 InputStream 的 read 读取它需要 3 个 OutputStream writes 来写入完整字符?

标签: java casting outputstream


【解决方案1】:

从技术上讲,演员没有理由。可能作者认为如果包括演员表,程序会更清晰。

【讨论】:

  • 谢谢你,亨利,这个答案。
【解决方案2】:

这里的演员表无关紧要,因为幸运的是在 BufferedOutputStream.write() 方法中 演员会发生。

public synchronized void write(int b) throws IOException {
    if (count >= buf.length) {
        flushBuffer();
    }
    buf[count++] = (byte)b;
}

正如文档所说,该方法只写入 8 个第一位,其余的将被忽略。 这就是将 int 类型转换为 byte 的效果。

我认为作者将演员表用于阐明将要写入输出的内容!这样,不知情的开发人员无需查阅 JavaDoc 即可查看将写入输出的内容!

尽可能地澄清你的代码总是好的做法。

P.S: 代码运行如下 然后 intByte 将转换为 byte 由于扩大 write(int) 方法的影响将被调用 剩下的……

【讨论】:

    【解决方案3】:

    通过将 intByte 强制转换为 byte,该值从 32 位缩小到 8 位。 write() 方法可以接受一个字节,即使它的签名要求一个 int ——这称为加宽(不需要强制转换)。那部分无关紧要。但是从intbyte 的转换很重要,因为它可以通过修剪前24 位来显着影响变量的值。例如,试试这个,看看会发生什么:

    int i = 13465878; byte b = (byte)i; System.out.println("i as a byte is " + b);

    【讨论】:

    • "i is a byte is 22" - 我的无知使我无法理解为什么是 22。
    • 感谢扩大方面。文件如何知道我正在从字节中读取整数?还是更谨慎地不要随意将整数转换为字节并认为一切都会顺利?转换在代码示例中没有任何损失,因为read 方法只获取一个字节,然后将其转换为一个 int,因此从该 int 中删除高 3 个字节不会做任何事情,用这种用法?跨度>
    • “有符号整数到整数类型 T 的窄化转换只会丢弃除 n 个最低位之外的所有位,其中 n 是用于表示类型 T 的位数。”在这里解释:docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3
    • 明白了,Richard :) 数字 13465878 的最低位是 00010110 ...这是 22。好,好,快了(ish)。谢谢!
    猜你喜欢
    • 2012-02-05
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 2010-10-30
    • 2020-02-03
    • 2011-08-19
    相关资源
    最近更新 更多