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
byte
andshort
using Java Virtual Machine instructions that sign-extend those values to values of typeint
at compile-time or run-time. Loads of literal values of typesboolean
andchar
are encoded using instructions that zero-extend the literal to a value of typeint
at compile-time or run-time. [..]. Thus, most operations on values of actual typesboolean
,byte
,char
, andshort
are 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.