Существуют ли какие-либо реальные способы использования примитивного типа байтов Java? - PullRequest
56 голосов
/ 01 августа 2011

По какой-то необъяснимой причине примитивный тип byte подписан в Java. Это означает, что действительными значениями являются -128..127 вместо обычного диапазона 0..255, представляющего 8 значащих бит в байте (без знакового бита).

Это означает, что весь код манипуляции байтами обычно выполняет целочисленные вычисления и в конечном итоге маскирует последние 8 бит.

Мне было интересно, существует ли какой-либо сценарий реальной жизни, где примитивный тип Java byte подходит идеально или это просто совершенно бесполезное дизайнерское решение?


РЕДАКТИРОВАТЬ: Единственный фактический случай использования был однобайтовый заполнитель для собственного кода. Другими словами, нельзя манипулировать байтом внутри кода Java.


РЕДАКТИРОВАТЬ: Теперь я видел место, где внутренняя тесная петля должна была делиться на 7 (числа 0..32), чтобы таблица поиска могла быть сделана с байтами в качестве типа данных, чтобы использование памяти могло быть ограничено Использование кеша L1. Это не относится к подписанному / неподписанному, но имело место фактическое использование.

Ответы [ 10 ]

33 голосов
/ 01 августа 2011

Джош Блох недавно упомянул в презентации , что это одна из ошибок в языке.

Я думаю, что причина этого в том, что в java нет числовых типов без знака, и byte должно соответствовать этому правилу. (Примечание: char не подписано, но не представляет цифры)

Что касается конкретного вопроса: я не могу придумать ни одного примера. И даже если бы были примеры, их было бы меньше, чем для 0..255, и они могли бы быть реализованы с использованием маскировки (а не большинства)

16 голосов
/ 01 августа 2011

byte, short, char типы в основном бесполезны, за исключением случаев, когда они используются в массивах для экономии места.

Ни Java , ни JVM не имеют никакой реальной поддержки для них. Почти все операции над ними будут продвигать их до int или long в первую очередь. Мы даже не можем написать что-то вроде

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

Тогда почему, черт возьми, вообще беспокоятся об операциях по определению типов byte, short, char?

Все, что они делают, это крадутся в расширяющихся конверсиях, которые удивят программиста.

10 голосов
/ 01 августа 2011

Удивительно, но я только что использовал byte в Java впервые на прошлой неделе, поэтому у меня есть (хотя и необычный) вариант использования. Я писал нативную функцию Java , которая позволяет вам реализовать функцию в библиотеке, которая может быть вызвана Java. Типы Java должны быть преобразованы в типы на родном языке, в данном случае C

Функция должна была принимать массив байтов, но (забывая о типе byte полностью в то время), я потребовал, чтобы она заняла char[]. Сигнатура, сгенерированная Java для функции C, дает тип этого параметра как jcharArray, который может быть преобразован в набор jchar с, которые определены в jni.h в unsigned short. Естественно, это не тот же самый размер - это 2 байта вместо 1. Это вызвало все виды проблем с базовым кодом. При получении типа Java byte[] в результате jbyteArray, а jbyte в Linux определяется с помощью typedef в signed char, который является правильным размером

4 голосов
/ 01 августа 2011

Оцифрованный звук (или любой другой сигнал) с 8-битными сэмплами со знаком кажется мне единственным разумным примером. Конечно, наличие подписанных байтов не является обязательным условием для обработки таких сигналов, и можно утверждать, что байт Java «идеально подходит».

Лично я считаю, что отсутствие подписи является ошибкой. Не только потому, что есть большее использование для беззнаковых байтов / целых, но потому что я предпочитаю более сильную систему типов. Было бы неплохо иметь возможность указать, что отрицательные числа недопустимы и разрешать проверки компилятором и исключения времени выполнения для нарушений.

3 голосов
/ 27 марта 2012

byte широко используется в разработке апплетов для Java Card.Поскольку карты имеют ограниченные ресурсы, каждый бит памяти драгоценен.Кстати, процессоры карты имеют ограничения в обработке целочисленных значений.Поддержка типа int является необязательной, а java.lang.String не поддерживается, поэтому все целочисленные операции и хранение данных осуществляются с помощью переменных и массивов byte и short.Поскольку целочисленные литералы имеют тип int, они должны быть явно приведены к byte или short во всем коде.Связь с картой осуществляется через команды APDU, которые передаются апплету в виде массива byte с, который должен быть разложен до byte с для декодирования класса команд, команд и параметров.Глядя на следующий код, вы видите, насколько типы byte и short важны для разработки Java-карт:

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

}
1 голос
/ 01 августа 2011

На машине со словами больше 8 бит это несколько полезно, если вы хотите сохранить множество значений, которые вписываются в 8-битный диапазон, в один массив, но обычно не рекомендуется использовать их иначе, так какНа самом деле byte - это больше усилий для выхода из памяти, чем int.

Помните, что Java была разработана для очень маленьких потребительских устройств (телевизионных приставок).Я ожидаю, что если бы он использовался таким образом на небольших 8-битных микропроцессорах, он был бы более полезен, так как точно соответствовал бы размеру слова и мог бы использоваться для общих операций "Math" в очень маленьком масштабе.

Единственная причина, по которой я вижу подпись, состоит в том, что неподписанный байт, взаимодействующий с int, может немного сбить с толку - но я не уверен, что это более запутанно, чем подписанный!

1 голос
/ 01 августа 2011

Я думаю, что это подписано, чтобы соответствовать short и int.

Что касается того, используется ли он много, то понятие «байтовые массивы» делает конструкцию, а не примитив.

Это действительно все, что у меня есть. :)

0 голосов
/ 01 мая 2016

Размер байта составляет 8 бит.Размер байта помогает в обработке ввода и вывода при выполнении таких функций, как запись в файл или чтение из файла.Рассмотрим сценарий, в котором вы хотите прочитать ввод с клавиатуры или из любого файла.Если вы используете «байтовую» структуру данных, вы знаете, что вы получаете один символ за раз, так как размер составляет 8 бит.Поэтому каждый раз, когда вы получаете входной поток, вы знаете, что фактически получаете один символ за раз.

0 голосов
/ 30 марта 2015

Я сейчас использую байты в Java для проекта Android с Bluetooth.

0 голосов
/ 04 июля 2013

Я часто использовал его, когда программировал программное обеспечение и игры для J2ME.На большинстве J2ME-устройств у вас ограниченные ресурсы, поэтому хранение, например, карты уровня в байтовом массиве требует меньше ресурсов, чем хранение в int-массиве.

...