Java Language


Primitive Data Types All Versions

Java SE 1.0
Java SE 1.1
Java SE 1.2
Java SE 1.3
Java SE 1.4
Java SE 5
Java SE 6
Java SE 7
Java SE 8
Java SE 9 (Early Access)

This draft deletes the entire topic.

Introduction

The 8 primitive data types byte, short, int, long, char, boolean, float, and double are the types that store most raw numerical data in Java programs.
expand all collapse all

Examples

  • 13

    A char can store a single 16-bit Unicode character. A character literal is enclosed in single quotes

    char myChar = 'u';
    char myChar2 = '5';
    char myChar3 = 65; // myChar3 == 'A'
    

    It has a minimum value of \u0000 (0 in the decimal representation, also called the null character) and a maximum value of \uffff (65,535).

    The default value of a char is \u0000.

    char defaultChar;    // defaultChar == \u0000
    

    In order to define a char of ' value an escape sequence (character preceded by a backslash) has to be used:

    char singleQuote = '\'';
    

    There are also other escape sequences:

    char tab = '\t';
    char backspace = '\b';
    char newline = '\n';
    char carriageReturn = '\r';
    char formfeed = '\f';
    char singleQuote = '\'';
    char doubleQuote = '\"'; // escaping redundant here; '"' would be the same; however still allowed
    char backslash = '\\';
    char unicodeChar = '\uXXXX' // XXXX represents the Unicode-value of the character you want to display
    

    You can declare a char of any Unicode character.

    char heart = '\u2764';
    System.out.println(Character.toString(heart)); // Prints a line containing "❤".
    

    It is also possible to add to a char. e.g. to iterate through every lower-case letter, you could do to the following:

    for (int i = 0; i <= 26; i++) {
        char letter = (char) ('a' + i);
        System.out.println(letter);
    }
    
  • 8

    A float is a single-precision 32-bit IEEE 754 floating point number. By default, decimals are interpreted as doubles. To create a float, simply append an f to the decimal literal.

    double doubleExample = 0.5;      // without 'f' after digits = double
    float floatExample = 0.5f;       // with 'f' after digits    = float
    
    float myFloat = 92.7f;           // this is a float...
    float positiveFloat = 89.3f;     // it can be positive,
    float negativeFloat = -89.3f;    // or negative
    float integerFloat = 43.0f;      // it can be a whole number (not an int)
    float underZeroFloat = 0.0549f;  // it can be a fractional value less than 0
    

    Floats handle the five common arithmetical operations: addition, subtraction, multiplication, division, and modulus.

    Note: The following may vary slightly as a result of floating point errors. Some results have been rounded for clarity and readability purposes (i.e. the printed result of the addition example was actually 34.600002).

    // addition
    float result = 37.2f + -2.6f;  // result: 34.6
    
    // subtraction
    float result = 45.1 - 10.3;    // result: 34.8
    
    // multiplication
    float result = 26.3f * 1.7f;   // result: 44.71
    
    // division
    float result = 37.1f / 4.8f;   // result: 7.729166
    
    // modulus
    float result = 37.1f % 4.8f;   // result: 3.4999971
    

    Because of the way floating point numbers are stored (i.e. in binary form), many numbers don't have an exact representation.

    float notExact = 3.1415926f;
    System.out.println(notExact); // 3.1415925
    

    While using float is fine for most applications, neither float nor double should be used to store exact representations of decimal numbers (like monetary amounts), or numbers where higher precision is required. Instead, the BigDecimal class should be used.

    The default value of a float is 0.0f.

    float defaultFloat;    // defaultFloat == 0.0f
    

    A float is precise to roughly an error of 1 in 10 million.

    Note: Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NaN are float values. NaN stands for results of operations that cannot be determined, such as dividing 2 infinite values. Furthermore 0f and -0f are different, but == yields true:

    float f1 = 0f;
    float f2 = -0f;
    System.out.println(f1 == f2); // true
    System.out.println(1f / f1); // Infinity
    System.out.println(1f / f2); // -Infinity
    System.out.println(Float.POSITIVE_INFINITY / Float.POSITIVE_INFINITY); // NaN
    
  • 6
    PrimitiveMemory SizeBoxed Type
    boolean1 byteBoolean
    byte1 byteByte
    short2 bytesShort
    char2 bytesChar
    int4 bytesInteger
    long8 bytesLong
    float4 bytesFloat
    double8 bytesDouble

    Boxed objects always require 8 bytes for type and memory management, and because the size of objects is always a multiple of 8, all boxed types require 16 bytes total. In addition, each usage of a boxed object entails storing a reference which accounts for another 4 or 8 bytes, depending on the JVM and JVM options.

    In data-intensive operations, memory consumption can have a major impact on performance. Memory consumption grows even more when using arrays: a float[5] array will require only 32 bytes; whereas a Float[5] storing 5 distinct non-null values will require 112 bytes total.

    Boxed value caches

    The space overheads of the boxed types can be mitigated to a degree by the boxed value caches. Some of the boxed types implement a cache of instances. For example, by default, the Integer class will cache instances to represent numbers in the range -128 to +127.

    If you create an instance of a boxed type either by autoboxing or by calling the static valueOf(primitive) method, the runtime system will attempt to use a cached value. If your application uses a lot of values in the range that is cached, then this can substantially reduce the memory penalty of using boxed types. Certainly, if you are creating boxed value instances "by hand", it is better to use valueOf rather than new. (The new operation always creates a new instance.)

Please consider making a request to improve this example.

Syntax

  • int aInt = 8; // The defining (number) part of this int declaration is called a literal.

  • int hexInt = 0x1a; // = 26; You can define literals with hex values prefixed with 0x.

  • int binInt = 0b11010; // = 26; You can also define binary literals; prefixed with 0b.

  • long goodLong = 10000000000L; // By default, integer literals are of type int. By adding the L at the end of the literal you are telling the compiler that the literal is a long. Without this the compiler would throw an "Integer number too large" error.

  • double aDouble = 3.14; // Floating-Point Literals are of type double by default.

  • float aFloat = 3.14F; // By default this literal would have been a double (and caused an "Incompatible Types" error), but by adding an F we tell the compiler it is a float.

Parameters

Parameters

Remarks

Java has 8 primitive data types, namely boolean, byte, short, char, int, long, float and double. (All other types are reference types. This includes all array types, and built-in object types / classes that have special significance in the Java language; e.g. String, Class and Throwable and its subclasses.)

The result of all operations (addition, subtraction, multiplication, etc) on a primitive type is at least an int, thus adding a short to a short produces an int, as does adding a byte to a byte, or a char to a char. If you want to assign the result of that back to a value of the same type, you must cast it. e.g.

byte a = 1;
byte b = 2;
byte c = (byte) (a + b);

Not casting the operation will result in a compile error.

This is due to the following part of the Java Language Spec, §2.11.1:

A compiler encodes loads of literal values of types byte and short using Java Virtual Machine instructions that sign-extend those values to values of type int at compile-time or run-time. Loads of literal values of types boolean and char are encoded using instructions that zero-extend the literal to a value of type int at compile-time or run-time. [..]. Thus, most operations on values of actual types boolean, byte, char, and short are correctly performed by instructions operating on values of computational type int.

The reason behind this is also specified in that section:

Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. [...] Separate instructions can be used to convert between unsupported and supported data types as necessary.

Still have a question about Primitive Data Types? Ask Question

Topic Outline