Hello! While going through JavaRush, you came across primitive types more than once. Here's a short list of what we know about them:
But, in addition to values, types also differ in memory size.
The type
- They are not objects and represent a value stored in memory
- There are several types of primitive types:
- Whole numbers -
byte
,short
,int
,long
- Floating point numbers (fractional) -
float
anddouble
- Boolean -
boolean
- Symbolic (to indicate letters and numbers) -
char
- Whole numbers -
- Each of them has its own range of values:
Primitive type | Size in memory | Range of values |
---|---|---|
byte | 8 bit | -128 to 127 |
short | 16 bit | to -32768 to 32767 |
char | 16 bit | from 0 to 65536 |
int | 32 bits | from -2147483648 to 2147483647 |
long | 64 bits | from -9223372036854775808 to 9223372036854775807 |
float | 32 bits | from (2 to the power -149) to ((2-2 to the power -23)*2 to the power 127) |
double | 64 bits | from (-2 to the power of 63) to ((2 to the power of 63) - 1) |
boolean | 8 (when used in arrays), 32 (when used in non-arrays) | true or false |
int
takes more than byte
. A long
- more than short
. The amount of memory occupied by primitives can be compared to nesting dolls: There is free space inside the nesting doll. The larger the nesting doll, the more space. long
We can easily put a smaller one inside a large nesting doll int
. It fits easily and you don’t need to do anything extra. In Java, when working with primitives, this is called automatic conversion. In another way it is called expansion. Here's a simple extension example:
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
byte littleNumber = 16;
bigNumber = littleNumber;
System.out.println(bigNumber);
}
}
Here we assign a value byte
to a variable int
. The assignment was successful and without any problems: the value stored in byte
occupies less memory space than it “fits” in int
. “Little nesting doll” (value byte
) easily fits into the “big matryoshka” (variable int
). It’s another matter when you try to do the opposite - put a large value into a variable that is not designed for such sizes. In principle, this trick will not work with real nesting dolls, but in Java it will work, but with nuances. Let's try to put a value int
into a variable short
:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = bigNumber;//error!
System.out.println(bigNumber);
}
Error! The compiler understands that you are trying to do something non-standard, and put a large matryoshka doll ( int
) inside a small one ( short
). A compilation error in this case is a warning from the compiler: “ Hey, are you sure you want to do this? “If you are sure, tell the compiler about it: “ Everything is ok, I know what I’m doing!” ” This process is called explicit type conversion, or narrowing . To make a narrowing, you need to explicitly indicate the type to which you want to cast your value. In other words, answer the compiler’s question: “ Well, which of these little dolls do you want to put this big doll in?” ” In our case it will look like this:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = (short) bigNumber;
System.out.println(littleNumber);
}
We explicitly indicated that we want to fit the value int
into a variable short
and take responsibility for it. The compiler, seeing an explicit indication of a narrower type, performs a conversion. What will be the result? Console output: -27008 A bit unexpected. Why exactly like this? It's actually simple. We had the original value - 10000000 It was stored in a variable int
that took up 32 bits, and in binary form it looked like this: We write this value to the variable short
, but it can only store 16 bits! Accordingly, only the first 16 bits of our number will be moved there, the rest will be discarded. As a result, the variable short
will contain the value , which in decimal form is exactly equal to -27008 That is why the compiler “asked for confirmation” in the form of an explicit cast to a specific type. Firstly, it shows that you take responsibility for the result, and secondly, it tells the compiler how much space to allocate when casting types. After all, if in the last example we had cast int
to type byte
, and not to short
, we would have only 8 bits at our disposal, not 16, and the result would have been different. For fractional types ( float
and double
), narrowing occurs differently. If you try to convert such a number to an integer type, its fractional part will be discarded.
public static void main(String[] args) {
double d = 2.7;
long x = (int) d;
System.out.println(x);
}
Console output: 2
Data type char
You already know that the char type is used to display individual characters.
public static void main(String[] args) {
char c = '!';
char z = 'z';
char i = '8';
}
But it has a number of features that are important to understand. Let's look again at the table with value ranges:
Primitive type | Size in memory | Range of values |
---|---|---|
byte | 8 bit | -128 to 127 |
short | 16 bit | -32768 to 32767 |
char | 16 bit | from 0 to 65536 |
int | 32 bits | from -2147483648 to 2147483647 |
long | 64 bits | from -9223372036854775808 to 9223372036854775807 |
float | 32 bits | from (2 to the power -149) to ((2-2 to the power -23)*2 to the power 127) |
double | 64 bits | from (-2 to the power of 63) to ((2 to the power of 63)-1) |
boolean | 8 (when used in arrays), 32 (when used in non-arrays) | true or false |
char
has a numeric range from 0 to 65536. But what does this mean? After all, char
these are not only numbers, but also letters, punctuation marks... The fact is that values char
are stored in Java in Unicode format. We have already encountered Unicode in one of the previous lectures. You probably remember that Unicode is a character encoding standard that includes characters from almost all written languages of the world. In other words, this is a list of special codes in which there is a code for almost any character from any language. The general Unicode table is very large and, of course, does not need to be learned by heart. Here, for example, is a piece of it: The main thing is to understand the principle of storing values char
, and remember that knowing the code of a specific symbol, you can always get it in the program. Let's try this with some random number:
public static void main(String[] args) {
int x = 32816;
char c = (char) x ;
System.out.println(c);
}
Console output: 耰 This is the format in which characters are stored in Java char
. Each character corresponds to a number - a numeric code of 16 bits, or two bytes. Unicode 32816 corresponds to the character 耰. Pay attention to this moment. In this example we used the variable int
. It occupies 32 bits of memory , while char
16 . Here we chose because the number we need, 32816, is out of range . Although the size , like short, is 16 bits, there are no negative numbers in the range, so the “positive” range is twice as large (65536 instead of 32767 ). We can use , as long as our code falls within the range of 65536. But if we create a number , it will take up more than 16 bits. And when narrowing down the types: int
short
char
char
char
short
int
int >65536
char c = (char) x;
the extra bits will be discarded, and the result will be quite unexpected.
Features of addition of char and integers
Let's look at this unusual example:
public class Main {
public static void main(String[] args) {
char c = '1';
int i = 1;
System.out.println(i+c);
}
}
Console output: 50 O_O Where is the logic? 1+1, where did 50 come from?! You already know that values char
are stored in memory as numbers in the range from 0 to 65536, representing the Unicode of our character. So here it is. When we perform addition char
and some integer type char
is converted to the number that corresponds to it in Unicode. When in our code we added 1 and '1', the symbol '1' was transformed to its code, which is 49 (you can check it in the table above). Therefore, the result became equal to 50. Let's once again take our old friend -耰as an example , and try to add it with some number.
public static void main(String[] args) {
char c = '耰';
int x = 200;
System.out.println(c + x);
}
Console output: 33016 We have already found out that耰corresponds to the code 32816. And when we add this number and 200, we get exactly our result - 33016 :) The mechanism of operation, as you can see, is quite simple.
GO TO FULL VERSION