由于一些莫名其妙的原因,byte
原始类型是用Java签名的。这意味着有效值为-128..127而不是通常的0..255范围,表示一个字节中的8个有效位(没有符号位)。
这意味着所有字节操作代码通常进行整数计算并最终屏蔽掉最后8位。
我想知道是否有任何真实生活场景,Java byte
原始类型完全适合或者它只是一个完全无用的设计决策?
编辑:唯一的实际用例是本机代码的单字节占位符。换句话说,不要将其作为Java代码中的字节进行操作。
编辑:我现在看到一个内部紧密循环需要除以7(数字0..32)的位置,因此可以使用字节作为数据类型来完成查找表,以便考虑L1缓存使用时内存使用率保持较低。这不是指签名/无签名,而是实际使用的情况。
令人惊讶的是,我上周第一次在Java中使用了byte
,所以我确实有一个(虽然不寻常)用例。我正在编写一个native Java function,它允许您在可以由Java调用的库中实现一个函数。需要将Java类型转换为本机语言中的类型,在本例中为C语言
该函数需要一个字节数组,但(当时完全忘记了byte
类型)我需要一个char[]
。为C函数生成的签名Java将该参数的类型赋予jcharArray
,它可以转换为一堆jchar
s,它们在jni.h
中被定义为unsigned short
。当然,这不是相同的大小 - 它是2个字节而不是1.这导致了底层代码的各种问题。制作Java类型byte[]
导致了jbyteArray
,而Linux上的jbyte
被定义为signed char
,这是正确的大小
我现在正在java中使用字节用于蓝牙android项目。
乔希布洛赫最近mentioned in a presentation认为这是该语言的错误之一。
我认为这背后的原因是java没有无符号数字类型,byte
应符合该规则。 (注意:char
是未签名的,但不代表数字)
至于具体问题:我想不出任何一个例子。即使有例子,它们也会少于0..255的那些,并且它们可以使用掩蔽(而不是大多数)来实现
byte, short, char
类型大多无用,除非在数组中使用以节省空间。
Java或JVM都没有任何真正的支持。几乎所有关于它们的操作都会首先将它们推广到int
或long
。我们甚至无法写出类似的东西
short a=1, b=2;
a = a + b; // illegal
a = a << 1; // illegal
那么为什么甚至会对byte, short, char
类型的定义操作感到麻烦呢?
他们所做的只是偷偷摸摸地扩大转换程序,这会给程序员带来惊喜。
具有8位带符号样本的数字化声音(或任何其他信号)对我来说似乎是唯一合理的例子。当然,签名字节不需要处理这些信号,可以说Java字节是否“完全适合”。
我个人认为没有签名是一个错误。不仅因为对无符号字节/整数的使用更多,而且因为我更喜欢更强大的类型系统。能够指定负数无效并允许编译器检查和违规的运行时异常会很好。
byte
在Java Card的applet开发中有广泛的用途。因为卡片资源有限,所以每一点内存都是宝贵的。顺便说一句,卡处理器在处理整数值方面存在局限性。 int
类型支持是可选的,并且不支持java.lang.String
,因此所有整数操作和数据存储都由byte
和short
变量和数组完成。由于整数文字是int
类型,它们应该在整个代码中显式地转换为byte
或short
。与卡的通信通过APDU命令传递给applet作为byte
s数组,应该分解为byte
s以解码命令类,指令和参数。查看以下代码,您会看到byte
和short
类型对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
}
我认为它是签名的,以便与short和int保持一致。
至于它是否被大量使用,它使“字节数组”的概念成为构造而不是原语。
这就是我的全部。 :)
在一个字大于8位的机器上,如果你希望将大量适合8位范围的值存储到单个数组中,这有点有用,但通常使用它们不是一个好主意,否则因为一个字节实际上是内存比int更多的努力。
请记住,Java是专为非常小的消费设备(机顶盒电视盒)而设计的。我希望如果它在小型8位微处理器上以这种方式使用它会更有用,因为它可以精确地适应字大小,并且可以用于非常小规模的一般“数学”操作。
我可以看到使其签名的唯一原因是与int交互的无符号字节可能有点令人困惑 - 但我不相信它比签名的更令人困惑!
字节大小为8位。字节大小有助于处理输入和输出,同时执行写入文件或从文件读取等功能。考虑一种情况,您希望从键盘或任何文件中读取输入。如果您使用“字节”数据结构,您知道您一次收到一个字符,因为大小是8位。因此,每次收到输入流时,您都知道您实际上一次只接收一个字符。
当我为J2ME编写软件和游戏时,我经常使用它。在大多数J2ME设备上,您的资源有限,因此在字节数组中存储级别的映射比将数据存储在int数组中要少得多。