Hello! While going through JavaRush, you came across primitive types more than once. Here's a short list of what we know about them:
  1. They are not objects and represent a value stored in memory
  2. There are several types of primitive types:
    • Whole numbers - byte, short, int,long
    • Floating point numbers (fractional) - floatanddouble
    • Boolean -boolean
    • Symbolic (to indicate letters and numbers) -char
  3. 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
But, in addition to values, types also differ in memory size. inttakes more than byte. A long- more than short. The amount of memory occupied by primitives can be compared to nesting dolls: Expansion and contraction of primitive types - 2 There is free space inside the nesting doll. The larger the nesting doll, the more space. longWe 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 byteto a variable int. The assignment was successful and without any problems: the value stored in byteoccupies 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 intinto 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 intinto a variable shortand 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 intthat took up 32 bits, and in binary form it looked like this: Expansion and contraction of primitive types - 3 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 shortwill contain the value Expansion and contraction of primitive types - 4, 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 intto 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 ( floatand 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
The type charhas a numeric range from 0 to 65536. But what does this mean? After all, charthese 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: Expansion and contraction of primitive types - 5 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 char16 . 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: intshortcharcharcharshortintint >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. Expansion and contraction of primitive types - 6 So here it is. When we perform addition charand some integer type charis 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 thatcorresponds 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.