In Java does anyone use short or byte?

Viewed 14429

Apart from using (byte[]) in streaming I don't really see byte and short used much. On the other hand I have seen long used where the actual value is |100| and byte would be more appropriate. Is this a consequence of the relative inexpensive nature of memory now or is this just minutia that developers needn't worry about?

12 Answers

Stephen C's answer above is incorrect. (Sorry I don't have enough reputation points to comment, so I have to post an answer here)

He stated

"You don't achieve any space saving by using byte or short in simple variables instead of int, because most Java implementations align stack variables and object members on word boundaries"

It's not true. The following is run on Oracle JDK1.8.0 , with jol

public class CompareShorts {
    public static void main(String[] args) {
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseInstance(new PersonalDetailA()).toPrintable());
        System.out.println(ClassLayout.parseInstance(new PersonalDetailB()).toPrintable());
    }
}
class PersonalDetailA {
     short height;
     byte color;
     byte gender;
}

class PersonalDetailB{
     int height;
     int color;
     int gender;
}

The output:

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

com.hunterstudy.springstudy.PersonalDetailA object internals:
 OFFSET  SIZE    TYPE DESCRIPTION                               VALUE
      0     4         (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4         (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4         (object header)                           82 22 01 f8 (10000010 00100010 00000001 11111000) (-134143358)
     12     2   short PersonalDetailA.height                    0
     14     1    byte PersonalDetailA.color                     0
     15     1    byte PersonalDetailA.gender                    0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

com.hunterstudy.springstudy.PersonalDetailB object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           e1 24 01 f8 (11100001 00100100 00000001 11111000) (-134142751)
     12     4    int PersonalDetailB.height                    0
     16     4    int PersonalDetailB.color                     0
     20     4    int PersonalDetailB.gender                    0
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

As you can see, the class instance using shorts and bytes takes 16 bytes, and the class instance using ints takes 24 bytes. So it does save eight bytes of memory per class instance.

The general information you come across is the fact that byte, generally byte [] is used in manipulating binary data, for example an image file, or while sending data over the network. I'll mention now, other use cases:

Encoding Strings in Java

In Java, the String object uses UTF-16, and the latter is immutable, i.e cannot be modified.

In order to encode strings, we convert them to UTF-8, which is compatible with ASCII. one way to do it, is to use java core, you can find out about more ways to go here.

To perform encoding, we copy the original string bytes to a byte array, and then create the desired one. Below, I'll give a simple example that shows why we need to encode strings, and how to do it:

  • Why is encoding important?

Imagine you have this German word "Tschüss" and you're using US-ASCII:

String germanString = "Tschüss";
byte[] germanBytes = germanString.getBytes();

String asciiEncodedString = new String(germanBytes,StandardCharsets.US_ASCII);

assertNotEquals(asciiEncodedString, germanString);

and the output will simply be:

Tsch?ss

Because US_ASCII doesn't recognize the "ü".

Now here's the example that works:

String germanString = "Tschüss";
byte[] germanBytes = germanString.getBytes(StandardCharsets.UTF_8);

String utf8EncodedString = new String(germanBytes, StandardCharsets.UTF_8);

assertEquals(germanString, utf8EncodedString);

byte[ ] Better than String in Performance Sometimes

For the record, Java String is an Object that uses char arrays under the hood, including other data, you can find more in this answer.

Now imagine the case where you want to parse a huge amount of string data and using for instance split method. In this case, you'll have different objects (different char arrays) spread in different locations in the memory, which results in worse locality to the CPU, contrary to the case where you have a byte array since the beginning in one location. You can find out more in this interesting post this one.

Related