byte, short, int, long, char, boolean, float, and double are the types that store most raw numerical data in Java programs.
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.
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
byteandshortusing Java Virtual Machine instructions that sign-extend those values to values of typeintat compile-time or run-time. Loads of literal values of typesbooleanandcharare encoded using instructions that zero-extend the literal to a value of typeintat compile-time or run-time. [..]. Thus, most operations on values of actual typesboolean,byte,char, andshortare correctly performed by instructions operating on values of computational typeint.
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.