1. List of primitive types
Java has 8 basic primitive types. They are called primitive because the values of these types are not objects and are stored directly inside variables.
Here is a table with some brief information about these types:
Type | Size in bytes |
Value range | Default value | Description |
---|---|---|---|---|
byte |
1 | -128 .. 127 | 0 |
The smallest integer type is a single byte |
short |
2 | -32,768 .. 32.767 | 0 |
Short integer, two bytes |
int |
4 | -2*109 .. 2*109 | 0 |
Integer, 4 bytes |
long |
8 | -9*1018 .. 9*1018 | 0L |
Long integer, 8 bytes |
float |
4 | -1038 .. 1038 | 0.0f |
Floating-point number, 4 bytes |
double |
8 | -10308 .. 10308 | 0.0d |
Double-precision floating point number, 8 bytes |
boolean |
1 | true , false |
false |
Boolean type (only true and false ) |
char |
2 | 0 .. 65.535 | '\u0000' |
Characters, 2 bytes, all greater than 0 |
By the way, here's an important nuance. If you declare an instance variable (field) or a static class variable and do not immediately assign any value to it, then it is initialized with a default value. The table presents a list of these values.
Local variables in a method have no default value. If you do not assign a value to such variables, they are considered uninitialized and cannot be used.
But let's return to primitive types and take a closer look at them.
2. Integer types
Java has 4 integer types: byte
, short
, int
and long
. They differ in their size and the range of values they can store.
int
type
The most commonly used is the int
type. The name comes from the word integer (whole number). All integer literals (whole numbers) in code are ints
(if they don't end in an L
, F
, or D
).
Variables of this type can take values from -2,147,483,648
to +2,147,483,647
.
That's a lot and is sufficient for almost every occasion. Almost every function that returns a number returns an int
.
Examples:
Code | Explanation |
---|---|
|
The length() method returns the length of a string |
|
The length field contains the length of the array. |
short
type
The short
type gets its name from short int
. It is also often called a short integer. Unlike the int
type, its length is only two bytes and the range of possible values is from -32,768
to +32,767
.
That means you can't store the number one million in it. Or even 50,000. This is the most rarely used integer type in Java. The main motivation for using it is to conserve memory.
Suppose you have a situation where you know in advance that you will be working with values that never exceed 30,000, and there will be millions of these values.
For example, let's say you're writing an application that processes ultra-high definition pictures that use 10
-bits per color. And you have a million pixels in your picture. This is a scenario where the decision to use int
or short
matters.
long
type
This type gets its name from long int
and is also called a long integer. Unlike the int
type, it has a fabulously enormous range of values: from -9*1018
to +9*1018
.
Why isn't it the basic integer type?
Because Java appeared in the mid-90s, when most computers were 32-bit. That means that all processors were optimized for working with numbers consisting of 32 bits. Processors could work with 64-bit integers, but operations with them were slower.
As a result, programmers reasonably decided to make int
the standard integer type, and to use the long
type only when truly necessary.
byte
type
This is smallest integer type in Java, but far from the least used. Its name, byte
, is also the word for the smallest addressable block of memory in Java.
There aren't that many valid values for the byte
type: from -128
to +127
. But that's not its strength. The byte
type is most often used when you need to store a large blob data in memory. An array of byte
s is ideal for this purpose.
Suppose you need to copy a file somewhere.
You don't need to process the contents of the file: you just want to create an area of memory (buffer), copy the contents of the file into it, and then write that data from the buffer to another file. A byte
array is what you need for this.
Keep in mind that an array variable only stores a reference to an area of memory. When the variable is passed to some method, only the memory address is passed. The block of memory itself is not copied.
byte[] buffer = new byte[1024*1024];
FileInputStream sourceFile = new FileInputStream("c:\\data.txt");
FileOutputStream destFile = new FileOutputStream("c:\\output.txt");
while (true)
{
int size = sourceFile.read(buffer); // Read data from a file into a buffer
destFile.write(buffer, 0, size); // Write data from the buffer to a file
// Stop copying if the buffer is not full
if (size < buffer.length) break;
}
sourceFile.close();
destFile.close();
3. Real types
The primitive types include two types for real numbers. Though it isn't entirely accurate to use that term. When computers handle real numbers, we call them floating-point numbers. The name comes from a standard for representing numbers, in which the integer and fractional parts of a number are separated by a period (a point, not a comma).
Each country has its own standards for writing numbers (surprise!).
Many people are accustomed to using periods to separate thousands and commas as the decimal separator: for example, they would write one million ones and 153 thousandths
as 1.000.000,153
. But in the United States, where Java's creators lived, a different standard was adopted: 1000000.153
Java has two floating-point primitive types: double
and float
.
As we said earlier, these types have a very specific internal arrangement: in fact, inside each variable of these types is not one number, but two:
For example, the floating-point number 987654.321
can be represented as 0.987654321*106
. Then in memory it will be represented as two numbers 987654321
(the mantissa, i.e. the significant part of the number) and 6
(exponent, i.e. a power of ten)
float
type
The name of the float
type comes from floating-point number. The size of this type is quite small — only 4 bytes (32 bits) — but it can store values from -3.4*1038
to 3.4*1038
. 24 bits are allocated for representing the mantissa, and 8 bits for the exponent. This type is capable of storing only 8 significant digits.
This approach makes it possible to store much larger numbers than an int
, while using the same 4 bytes. But to do so, we sacrifice accuracy. Because part of the memory stores the mantissa, these variables store only 6-7 decimal places while the rest are discarded.
Example:
Code | Value |
---|---|
|
123.45679 |
|
12346.0 |
|
-1.2345679 |
As you can see, this type's main drawback is the very small number of significant digits, and the loss of precision as soon as the eighth digit. That's why the float
type is not very popular among Java programmers.
double
type
The double
type is the standard floating-point type. The name comes from double precision floating-point number. All real literals are double
s by default.
This type takes up 8 bytes of memory (64 bits) and can store values from -1.7*10308
to 1.7*10308
. An important thing to know is that 53 bits are allocated for the mantissa, while the remaining 11 are for the exponent.
This allows 15-17 significant digits to be stored.
Example:
Code | Value |
---|---|
|
1234567890.1234567 |
|
1234567890.1234512 |
|
1234567890.1357913 |
This precision, especially in comparison with the float
type, is decisive: 99% of all operations with real numbers are performed using the double
type.
11
bits are allocated for the exponent, which means you can store powers of ten from -323
to +308
(that's a power of two from -1024
to +1023
). The double
type can easily store a number with hundreds of zeros after the decimal point:
Code | Value |
---|---|
|
600.0 |
4. Infinity
Floating-point numbers have another interesting feature: they can store a special value denoting infinity. And you can represent positive infinity and negative infinity.
Examples:
Code | Note |
---|---|
|
|
|
|
|
|
If infinity is multiplied by a number, you get infinity. If you add a number to infinity, you get infinity. That's super convenient.
Not a number (NaN
)
Any operations involving infinity yield infinity. Well, most but not all.
Floating-point numbers can store another special value: NaN
. It is short for Not a Number (not a number).
In mathematics, if you divide infinity by infinity, the result is undefined.
But, in Java, if you divide infinity by infinity, the result is NaN
.
Examples:
Code | Note |
---|---|
|
|
|
|
|
|
Any operation with NaN
yields NaN
.
5. char
type
Among Java's primitive types, one deserves some special attention: the char
type. Its name comes from the word character, and the type itself is used to store characters.
Characters are what strings are made of, right? Strings are an array of characters.
But even more interesting is the fact that the char
type is also a numeric type! It's a dual purpose type, so to speak.
The reality is that the char
type doesn't actually characters. Instead, it stores character codes from the Unicode encoding. Each character corresponds to a number: the character's numeric code.
Each char
variable occupies two bytes in memory (the same as the short
type). But unlike the short
type, the char
integer type is unsigned and can store values from 0
to 65,535
.
The char
type is a hybrid type. Its values can be interpreted both as numbers (e.g. they can be added and multiplied) and as characters. This was done because although characters are visual representations, to a computer they are above all just numbers. And it's much more convenient to work with them as numbers.
Unicode
Unicode is a special table (encoding) that contains all the characters in the world. And each character has its own number. It looks approximately like this:
There are different ways to assign a value to a char
variable.
Code | Description |
---|---|
|
The a variable will contain the Latin letter A . |
|
The a variable will contain the Latin letter A . Its code is 65 . |
|
The a variable will contain the Latin letter A .Its code is 65 , which equals 41 in the hexadecimal system.
|
|
The a variable will contain the Latin letter A .Its code is 65 , which equals 41 in the hexadecimal system.The two extra zeros don't change anything. |
|
The a variable will contain the Latin letter A .Another way to define a character by its code. |
Most often, people simply indicate the character in quotation marks (as in the first row of the table). That said, the latter method is also popular. Its advantage is that it can be used in strings.
And as we said, the char
type is also an integer type, so you can write something like this:
Code | Console output |
---|---|
|
The Latin letter B will be displayed on the screen.Because: A – 65 B – 66 C – 67 |
Working with char
s
Each char
is first of all a number (character code), and then a character. If you know a character code, you can always get the character in your program. Example:
Code | Console output |
---|---|
|
|
Standard codes
Here are the most well-known character codes:
Characters | Codes |
---|---|
0 , 1 , 2 , ... 9 |
48 , 49 , 50 , ... 57 |
a , b , c , ... z |
97 , 98 , 99 , ... 122 |
A , B , C , ... Z |
65 , 66 , 67 , ... 90 |
6. boolean
type
And the last primitive type is boolean
.
As you already know, it can only take two values: true
and false
.
And with that, you already know everything there is to know about this type.
GO TO FULL VERSION