Existe-t-il des utilisations réelles pour le type primitif d’octet Java?

Pour une raison inexplicable, le type primitif d’ byte est signé en Java. Cela signifie que les valeurs valides sont -128..127 au lieu de la plage 0..255 habituelle représentant 8 bits significatifs dans un octet (sans bit de signe).

Cela signifie que le code de manipulation de tous les octets effectue généralement des calculs entiers et finit par masquer les 8 derniers bits.

Je me demandais s’il existe un scénario réel dans lequel le type primitif d’ byte Java convient parfaitement ou s’il s’agit simplement d’une décision de conception totalement inutile?


EDIT: Le seul cas d’utilisation réel était un espace réservé à un octet pour le code natif. En d’autres termes, ne pas être manipulé comme un octet dans le code Java.


EDIT: J’ai maintenant vu un endroit où une boucle serrée interne devait être divisée par 7 (numéros 0..32), donc une table de consultation pourrait être faite avec des octets comme type de données afin que l’utilisation de la mémoire . Cela ne fait pas référence à la signature / unsignedness mais était un cas d’utilisation réelle.

Étonnamment, je viens d’utiliser l’ byte en Java pour la première fois la semaine dernière, donc j’ai un cas d’utilisation (quoique inhabituel). J’écrivais une fonction Java native , qui vous permet d’implémenter une fonction dans une bibliothèque pouvant être appelée par Java. Les types Java doivent être convertis en types dans le langage natif, dans ce cas C

La fonction devait prendre un tableau d’octets, mais (en oubliant complètement le type d’ byte à ce moment-là) je devais prendre un caractère char[] . La signature générée par Java pour la fonction C donne le type de ce paramètre en tant que jcharArray , qui peut être converti en un groupe de jchar s, typedef-ed en jni.h à unsigned short . Bien entendu, ce n’est pas la même taille – il s’agit de 2 octets au lieu de 1. Cela a causé toutes sortes de problèmes avec le code sous-jacent. L’ byte[] type Java byte[] généré un jbyteArray et jbyte sous Linux est jbyteArray un jbyteArray signed char , ce qui correspond à la taille correcte

Josh Bloch a récemment mentionné dans une présentation qu’il s’agissait d’une des erreurs dans la langue.

Je pense que la raison derrière cela est que java n’a pas de types numériques non signés et que l’ byte doit être conforme à cette règle. (Remarque: char est non signé, mais ne représente pas des nombres)

En ce qui concerne la question particulière: je ne peux penser à aucun exemple. Et même s’il y avait des exemples, ils seraient moins nombreux que ceux de 0..255, et ils pourraient être mis en œuvre en utilisant le masquage (plutôt que la majorité)

byte, short, char types de caractères sont pour la plupart inutiles, sauf lorsqu’ils sont utilisés dans des tableaux pour économiser de l’espace.

Ni Java, ni JVM ne les supportent réellement. Presque toutes les opérations sur eux les feront passer en premier ou en long . Nous ne pouvons même pas écrire quelque chose comme

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

Alors pourquoi diable même de définir des opérations sur les types d' byte, short, char ?

Tout ce qu'ils font, ce sont des conversions qui vont surprendre le programmeur.

Le son numérisé (ou tout autre signal) avec des échantillons signés 8 bits semble être le seul exemple raisonnable pour moi. Bien sûr, avoir des octets signés n’est pas nécessaire pour gérer de tels signaux et on peut dire que l’octet Java “convient parfaitement”.

Personnellement, je pense que ne pas avoir signé est une erreur. Non seulement parce que les octets / ints non signés sont plus utilisés, mais parce que je préfère un système de type plus fort. Il serait bon de pouvoir spécifier que les nombres négatifs ne sont pas valides et autoriser les vérifications du compilateur et les exceptions d’exécution pour les violations.

byte a une utilisation extensive dans le développement d’applets pour Java Card. Les cartes ayant des ressources limitées, chaque bit de mémoire est précieux. En passant, les processeurs de cartes ont des limitations dans le traitement des valeurs entières. int prise en charge de type int est facultative et java.lang.Ssortingng n’est pas pris en charge, donc toutes les opérations sur les entiers et les données sont effectuées par byte , variables short et tableaux. Comme les littéraux entiers sont de type int , ils doivent être explicitement convertis en byte ou en code entier. La communication avec la carte passe par les commandes APDU qui sont envoyées à applet sous la forme d’un tableau d’ byte s à décomposer en byte pour décoder la classe de commandes, les instructions et les parameters. En regardant le code suivant, vous voyez combien d’ byte et de types short sont importants pour le développement de 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 } 

Je pense qu’il est signé afin d’être cohérent avec short et int.

Quant à savoir si elle est beaucoup utilisée, cela fait de la notion de “tableaux d’octets” une construction plutôt qu’une primitive.

C’est vraiment tout ce que j’ai. 🙂

Sur une machine avec des mots de plus de 8 bits, cela peut être utile si vous souhaitez stocker un grand nombre de valeurs comsockets dans une plage de 8 bits dans un seul tableau, mais ce n’est généralement pas une bonne idée, car un octet est en fait plus d’effort pour sortir de la mémoire qu’un int.

Rappelez-vous cependant que Java a été conçu pour les très petits appareils grand public (décodeurs TV). J’imagine que si cela avait été utilisé de cette façon sur les petits microprocesseurs 8 bits, cela aurait été plus utile car il correspondrait exactement à la taille des mots et pourrait être utilisé pour des opérations “mathématiques” à très petite échelle.

La seule raison pour laquelle je peux le faire signer est qu’un octet non signé interagissant avec un int peut être un peu déroutant – mais je ne suis pas convaincu que ce soit plus déroutant qu’un signé!

La taille de l’octet est de 8 bits. La taille de l’octet aide à traiter les entrées et les sorties tout en exécutant des fonctions telles que l’écriture dans un fichier ou la lecture d’un fichier. Considérons un scénario dans lequel vous souhaitez lire une entrée du clavier ou de n’importe quel fichier. Si vous utilisez la structure de données “octet”, vous savez que vous recevez un caractère à la fois car la taille est de 8 bits. Ainsi, chaque fois que vous recevez un stream d’entrée, vous savez que vous recevez en réalité un personnage à la fois.

Je l’ai utilisé fréquemment lorsque je programmais des logiciels et des jeux pour J2ME. Sur la plupart des périphériques J2ME, vous disposez de ressources limitées. Par exemple, stocker la carte d’un niveau dans un tableau d’octets demande moins de ressources que de la stocker dans un int-tableau.

J’utilise des octets en ce moment dans Java pour un projet Android Bluetooth.