Java _signed_ byte 基元类型在现实生活中有什么用途吗?

发布于 2024-11-27 03:21:33 字数 422 浏览 0 评论 0原文

由于某些莫名其妙的原因,byte 基元类型在 Java 中是有符号的。这意味着有效值为 -128..127,而不是通常的 0..255 范围,表示一个字节中的 8 个有效位(没有符号位)。

这意味着所有字节操作代码通常都会进行整数计算并最终屏蔽掉最后 8 位。

我想知道在现实生活中是否存在 Java byte 基元类型完全适合的场景,或者这只是一个完全无用的设计决策?


编辑:唯一的实际用例是本机代码的单字节占位符。换句话说,不能在 Java 代码中作为字节进行操作。


编辑:我现在看到一个地方,内部紧密循环需要除以 7(数字 0..32),因此可以使用字节作为数据类型来完成查找表,这样考虑到 L1 缓存使用情况,内存使用量可以保持较低水平。这不是指有符号/无符号,而是实际使用的情况。

For some inexplicable reason the byte primitive type is signed in Java. This mean that valid values are -128..127 instead of the usual 0..255 range representing 8 significant bits in a byte (without a sign bit).

This mean that all byte manipulation code usually does integer calculations and end up masking out the last 8 bits.

I was wondering if there is any real life scenario where the Java byte primitive type fits perfectly or if it is simply a completely useless design decision?


EDIT: The sole actual use case was a single-byte placeholder for native code. In other words, not to be manipulated as a byte inside Java code.


EDIT: I have now seen a place where an inner tight loop needed to divide by 7 (numbers 0..32) so a lookup table could be done with bytes as the datatype so the memory usage could be kept low thinking of L1 cache usage. This does not refer to the signed/unsignedness but was a case of an actual usage.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

铁憨憨 2024-12-04 03:21:33

Josh Bloch 最近在演示中提到这是该语言中的错误之一。

我认为这背后的原因是java没有无符号数字类型,而byte应该符合该规则。 (注意:char是无符号的,但不代表数字)

至于特定问题:我想不出任何例子。即使有示例,它们也会比 0..255 的示例少,并且可以使用掩码(而不是大多数)来实现

Josh Bloch recently mentioned in a presentation that this is one of the mistakes in the language.

I think the reason behind this is that java does not have unsigned numeric types, and byte should conform to that rule. (Note: char is unsigned, but does not represent numbers)

As for the particular question: I can't think of any example. And even if there were examples, they would be fewer than the ones for 0..255, and they could be implemented using masking (rather than the majority)

毅然前行 2024-12-04 03:21:33

byte、short、char 类型大多无用,除非在数组中使用以节省空间。

JavaJVM 都没有对它们提供任何真正的支持。几乎所有对它们的操作都会首先将它们提升为 intlong。我们甚至无法编写类似的内容

short a=1, b=2;
a = a + b;  // illegal
a = a << 1; // illegal

那么为什么还要费心在 byte、short、char 类型上定义操作呢?

他们所做的只是偷偷地扩大转换,这会让程序员感到惊讶。

byte, short, char types are mostly useless, except when used in arrays to save space.

Neither Java or JVM has any real support for them. Almost all operations on them will promote them to int or long first. We cannot even write something like

short a=1, b=2;
a = a + b;  // illegal
a = a << 1; // illegal

Then why the heck even bother with defining operations on byte, short, char types at all?

All they do are sneaking in widening conversions that will surprise the programmer.

令人惊讶的是,我上周刚刚在 Java 中第一次使用了 byte,所以我确实有一个(尽管不寻常的)用例。我正在编写一个 本机 Java 函数,它可以让您在库中实现一个可以调用的函数通过Java。 Java 类型需要转换为本机语言中的类型,在本例中,C

函数需要采用字节数组,但是(当时完全忘记了 byte 类型)我让它采用了一个char[]。 Java 为 C 函数生成的签名将该参数的类型指定为 jcharArray,它可以转换为一堆 jchar,并在 中进行类型定义>jni.h无符号短。当然,这不是相同的大小——它是 2 个字节而不是 1 个字节。这导致了底层代码的各种问题。将 Java 类型 byte[] 生成 jbyteArray,Linux 上的 jbyte 被 typedef 为 signed char >,这是正确的尺寸

Amazingly, I just used byte in Java for the first time last week, so I do have an (albeit unusual) use-case. I was writing a native Java function, which lets you implement a function in a library that can be called by Java. Java types need to be converted to types in the native language, in this case C

The function needed to take an array of bytes, but (forgetting about the byte type entirely at the time) I had it take a char[]. The signature Java generates for the C function gives the type of that parameter as jcharArray, which can be converted to a bunch of jchars, which are typedef-ed in jni.h to unsigned short. Naturally, that is not the same size -- it's 2 bytes instead of 1. This caused all sorts of problems with the underlying code. Making the Java type byte[] resulted in a jbyteArray, and jbyte on Linux is typedef-ed to signed char, which is the right size

☆獨立☆ 2024-12-04 03:21:33

对我来说,带有 8 位签名样本的数字化声音(或任何其他信号)似乎是唯一合理的例子。当然,处理此类信号并不需要有符号字节,并且可以争论 Java 字节是否“完美适合”。

我个人认为没有未签名是一个错误。不仅因为无符号字节/整数有更多用途,而且因为我更喜欢更强大的类型系统。如果能够指定负数无效并允许编译器检查和运行时异常以检查违规情况,那就太好了。

Digitized sound (or any other signal) with 8 bit signed samples seems like the only reasonable example to me. Of course having signed bytes is no requirement to handling such signals and it can be argued whether Java byte "fits perfectly".

Personally I think not having unsigned is a mistake. Not only because there's more use for unsigned bytes/ints but because I prefer a stronger type system. It would be nice to be able to specify that negative numbers are not valid and allow compiler checks and runtime exceptions for violations.

祁梦 2024-12-04 03:21:33

byte 在 Java Card 的 applet 开发中有着广泛的用途。由于卡片的资源有限,每一点记忆都非常宝贵。顺便说一句,卡处理器在处理整数值方面有限制。 int 类型支持是可选的,不支持 java.lang.String,因此所有整数操作和数据存储都是通过 byte完成的短变量和数组。由于整数文字是 int 类型,因此应在整个代码中将它们显式转换为 byteshort 。与卡的通信通过 APDU 命令进行,该命令作为字节数组传递给小程序,该数组应分解为字节以解码命令类、指令和参数。查看以下代码,您会发现 byteshort 类型对于 Java Card 开发有多重要:

package somepackage.SomeApplet;

import javacard.framework.*;
import org.globalplatform.GPSystem;
import org.globalplatform.SecureChannel;

public class SomeApplet extends Applet {

    // Card status
    private final static byte ST_UNINITIALIZED     = (byte) 0x01;
    private final static byte ST_INITIALIZED       = (byte) 0x02;

    // Instructions & Classes
    private final static byte PROP_CLASS           = (byte) 0x80;     

    private final static byte INS_INIT_UPDATE      = (byte) 0x50;
    private final static byte INS_EXT_AUTH         = (byte) 0x82;

    private final static byte INS_PUT_DATA         = (byte) 0xDA;
    private final static byte INS_GET_RESPONSE     = (byte) 0xC0;
    private final static byte INS_GET_DATA         = (byte) 0xCA;


    private final static short SW_CARD_NOT_INITIALIZED       = (short) 0x9101;  
    private final static short SW_CARD_ALREADY_INITIALIZED   = (short) 0x9102;  

    private final static byte OFFSET_SENT = 0x00;
    private final static byte OFFSET_RECV = 0x01;
    private static short[] offset;

    private static byte[] fileBuffer;
    private static short fileSize = 0;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new SomeApplet( bArray, bOffset, bLength);
    }

    public RECSApplet(byte[] bArray, short bOffset, byte bLength) {
        offset = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET);
        fileBuffer = new byte[FILE_SIZE];

        byte aidLen = bArray[bOffset];
        if (aidLen== (byte)0){
            register();
        } else {
            register(bArray, (short)(bOffset+1), aidLen);
        }
    }

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return;
        }
        byte[] buffer = apdu.getBuffer();
        short len = apdu.setIncomingAndReceive(); 

        byte cla = buffer[ISO7816.OFFSET_CLA];
        byte ins = buffer[ISO7816.OFFSET_INS];
        short lc = (short) (buffer[ISO7816.OFFSET_LC] & 0x00ff); 

        while (len < lc) {
            len += apdu.receiveBytes(len);
        }

        SecureChannel sc = GPSystem.getSecureChannel();
        if ((short)(cla & (short)0x80) == ISO7816.CLA_ISO7816) {
            switch (ins) {
                case INS_PUT_DATA:
                    putData(buffer, ISO7816.OFFSET_CDATA, offset[OFFSET_RECV], len);

                    if ((cla & 0x10) != 0x00) {
                        offset[OFFSET_RECV] += len;
                    } else {
                        fileSize = (short) (offset[OFFSET_RECV] + len);
                        offset[OFFSET_RECV] = 0;
                    }
                    return;

                case INS_GET_DATA:
                case INS_GET_RESPONSE:
                    sendData(apdu);
                    return;
                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }

        }
        else if ((byte) (cla & PROP_CLASS) == PROP_CLASS) {
            switch (ins) {
                case INS_INIT_UPDATE:
                case INS_EXT_AUTH:
                    apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, sc.processSecurity(apdu));
                    return;
                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }
        } else
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }

    // Some code omitted

}

byte has an extensive use in applet development for Java Card. Because cards have limited resources every bit of memory is precious. By the way card processors have limitations in processing of integer values. int type support is optional and java.lang.String is not supported so all integer operation and data storage is done by byte and short variables and arrays. As integer literals are of int type, they should be explicitly cast to byte or short in whole code. Communication with card goes through APDU commands that is handed to applet as an array of bytes that should be decomposed to bytes to decode command class, instruction and parameters. Looking at the following code you see how much byte and short types are important to Java Card development:

package somepackage.SomeApplet;

import javacard.framework.*;
import org.globalplatform.GPSystem;
import org.globalplatform.SecureChannel;

public class SomeApplet extends Applet {

    // Card status
    private final static byte ST_UNINITIALIZED     = (byte) 0x01;
    private final static byte ST_INITIALIZED       = (byte) 0x02;

    // Instructions & Classes
    private final static byte PROP_CLASS           = (byte) 0x80;     

    private final static byte INS_INIT_UPDATE      = (byte) 0x50;
    private final static byte INS_EXT_AUTH         = (byte) 0x82;

    private final static byte INS_PUT_DATA         = (byte) 0xDA;
    private final static byte INS_GET_RESPONSE     = (byte) 0xC0;
    private final static byte INS_GET_DATA         = (byte) 0xCA;


    private final static short SW_CARD_NOT_INITIALIZED       = (short) 0x9101;  
    private final static short SW_CARD_ALREADY_INITIALIZED   = (short) 0x9102;  

    private final static byte OFFSET_SENT = 0x00;
    private final static byte OFFSET_RECV = 0x01;
    private static short[] offset;

    private static byte[] fileBuffer;
    private static short fileSize = 0;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new SomeApplet( bArray, bOffset, bLength);
    }

    public RECSApplet(byte[] bArray, short bOffset, byte bLength) {
        offset = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET);
        fileBuffer = new byte[FILE_SIZE];

        byte aidLen = bArray[bOffset];
        if (aidLen== (byte)0){
            register();
        } else {
            register(bArray, (short)(bOffset+1), aidLen);
        }
    }

    public void process(APDU apdu) {
        if (selectingApplet()) {
            return;
        }
        byte[] buffer = apdu.getBuffer();
        short len = apdu.setIncomingAndReceive(); 

        byte cla = buffer[ISO7816.OFFSET_CLA];
        byte ins = buffer[ISO7816.OFFSET_INS];
        short lc = (short) (buffer[ISO7816.OFFSET_LC] & 0x00ff); 

        while (len < lc) {
            len += apdu.receiveBytes(len);
        }

        SecureChannel sc = GPSystem.getSecureChannel();
        if ((short)(cla & (short)0x80) == ISO7816.CLA_ISO7816) {
            switch (ins) {
                case INS_PUT_DATA:
                    putData(buffer, ISO7816.OFFSET_CDATA, offset[OFFSET_RECV], len);

                    if ((cla & 0x10) != 0x00) {
                        offset[OFFSET_RECV] += len;
                    } else {
                        fileSize = (short) (offset[OFFSET_RECV] + len);
                        offset[OFFSET_RECV] = 0;
                    }
                    return;

                case INS_GET_DATA:
                case INS_GET_RESPONSE:
                    sendData(apdu);
                    return;
                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }

        }
        else if ((byte) (cla & PROP_CLASS) == PROP_CLASS) {
            switch (ins) {
                case INS_INIT_UPDATE:
                case INS_EXT_AUTH:
                    apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, sc.processSecurity(apdu));
                    return;
                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }
        } else
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }

    // Some code omitted

}
心安伴我暖 2024-12-04 03:21:33

我认为是为了与short和int保持一致而进行签名的。

至于它是否被大量使用,它使“字节数组”的概念成为一种构造而不是原语。

这就是我所拥有的一切。 :)

I think it is signed in order to be consistent with short and int.

As to whether it is used much, it makes the notion of "byte arrays" a construct rather than a primitive.

That's really all I have. :)

淡墨 2024-12-04 03:21:33

在字数大于 8 位的机器上,如果您希望将大量适合 8 位范围的值存储到单个数组中,那么它会很有用,但通常使用它们并不是一个好主意,因为字节实际上是与 int 相比,要付出更多努力才能摆脱内存。

请记住,Java 是为非常小的消费设备(机顶电视盒)设计的。我预计如果它在小型 8 位微处理器上以这种方式使用,它会更有用,因为它完全适合字长,并且可以用于非常小规模的一般“数学”运算。

我认为使其签名的唯一原因是,与 int 交互的无符号字节可能有点令人困惑 - 但我不相信它比签名字节更令人困惑!

On a machine with words larger than 8 bits it's somewhat useful if you wish to store a lot of values that fit in an 8-bit range into a single array, but typically it's not a good idea to use them otherwise since a byte is actually more effort to get out of memory than an int.

Remember though that Java was designed for very small consumer devices (set-top TV boxes). I expect if it had been used this way on small 8-bit microprocessors it would have been more useful as it would fit the word size exactly and could be used for general "Math" operations on a very small scale.

The only reason I can see to make it signed is that an unsigned byte interacting with an int can be a little confusing--but I'm not convinced it's any more confusing than a signed one is!

不爱素颜 2024-12-04 03:21:33

字节的大小是8位。字节大小有助于在执行写入文件或从文件读取等功能时处理输入和输出。考虑一个场景,您想要从键盘或任何文件读取输入。如果您使用“字节”数据结构,您就知道一次接收一个字符,因为大小为 8 位。因此,每次收到输入流时,您都知道您实际上一次收到一个字符。

The size of byte is 8 bits. The size of byte helps in processing input and output while performing functions like writing to a file or reading from a file. Consider a scenario in which you want to read an input from the keyboard or from any file. If you use the "byte" data structure, you know that you are receiving one character at a time since the size is 8 bits. So every time you receive an input stream, you know that you are actually receiving one character at a time.

丶视觉 2024-12-04 03:21:33

当我为 J2ME 编写软件和游戏时,我经常使用它。在大多数 J2ME 设备上,资源有限,因此将关卡映射存储在字节数组中比将其存储在 int 数组中占用的资源更少。

I used it frequently when I was programming software and games for J2ME. On most J2ME-devices, you have limited resources, so storing for example the map of a level in a byte-array is less resource-intensive than storing it in an int-array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文