Primitive Data Types

Java supports a variety of primitive data types, from numeric to character based. These data types allow the storage of data in many different forms that use different amounts of memory. You will use these different data types to store many different values (such as someone's age, as we have already seen).

Numeric Data Types

The numeric data types can be split up into two areas: integers and floating-point.


Integers are data values used for explicitly storing whole numbers, such as 3, 7022, or –99. The value 3.14, for example, is not an integer value but is known as a floating-point value, as we shall see a little later in this chapter. The following table shows the four integer type variables available in Java, their range, and the amount of memory they use.

Integer Type


Memory (bytes)


–128 to 127



–32768 to 32767



–2147483648 to 2147483647



–9223372036854775808 to 9223372036854775807



There are no unsigned types available explicitly in Java. In many other coding languages, the use of unsigned numeric data types indicates that the value stored will only be positive, meaning the positive value range is doubled. For instance, an unsigned byte would have the range 0 to 255 instead of –128 to 127.

In order to use a variable, it must be declared, which simply states that you are creating the variable of a specified data type. There are a number of ways in which you can declare a variable. The simplest way is as follows:

int numberA;

This is the standard way in which all variables are declared—by entering the type of data followed by a name that you must specify. Java is a case-sensitive language. This means that if we have just declared the variable numberA, trying to access this variable by typing NUMBERA will not work. In other languages, such as Pascal, this would be okay.


Variable names must begin with a letter or an underscore (_) character (not a number). Also, you cannot use any of the reserved keywords as variable names.

The previous code creates a variable of type int called numberA. If you want to declare another variable, you can repeat this code, specifying a different name instead of numberA, as follows:

int numberA;
int numberB;

Conveniently, you can also do this in one line using a comma (,) to separate the variables.

int numberA, numberB;

The value of a variable can also be assigned when the variable is declared.

int numberA = 128, numberB = -64;

You do not have to set values for both if you do not want to.

// set numberA's value only int numberA = 128, numberB;
// or set numberB's value only int numberA, numberB = -64;

Then you can assign values later on in the code now that the variables have been declared.

// set numberA to 77
numberA = 77;
// set the value of numberB to the value of numberA.
numberB = numberA;

We talked before about objects and references to objects, and that the primitive data types are not references; if you set numberB equal to numberA, the value of numberB will be set equal to that of the value of numberA. They will not reference the same memory, so changes made to one will not affect the other later on in the code.

numberA = 77;
numberB = numberA;
numberA = 101;
// numberB remains equal to 77

Converting between Integer Data Types

Integer values are of type int by default. That is, any number that you hard-code, like the value 77 that we just assigned to the variable numberA, will have the range of the data type int, as shown in the integer range table on the previous page. This means that when declaring values to variables of type long, you must specify in the code that the number entered is also of type long and not of type int. For example, an attempt to set a variable of type long to a value exceeding the limit of an int (either less than –2147483648 or greater than 2147483647) will cause a compiler error.

long myNumber = 3000000000; // this will not compile

In order to tell the compiler that you want the value 3000000000 (that is, 3 with nine zeros) to be of type long, you must add the letter L (or the unadvisable lowercase l, as this looks like the number 1) onto the end of the number.

long myNumber = 3000000000L; // this will compile

Another problem is setting the value of one integer data type from the value of another integer data type that is larger in range. Let's say we have the following four variables:

byte numberByte = 27;
short numberShort = 2001;
int numberInt = 55000;
long numberLong = 30000000000L;

The following statements will be fine:

numberShort = numberByte; // short has greater range than byte numberLong = numberShort; // long has greater range than short

The variable being assigned a value must be of a data type smaller than or equal to the data type of the variable from which it is being assigned; otherwise, a method called typecasting must be used to tell the compiler to convert the assigned value to that of an acceptable data type. In actual fact, when we converted the previous valid data type values, this was known as implicit casting, where we know that the data can be validly assigned. The real typecasting that we refer to is known as explicit casting. This is where the cast must be defined in the code itself to alert you of the dangers involved in the cast (e.g., possible loss of data), allowing you to make sure you are prepared to lose data if that is the case.

numberShort = numberLong; // this will not compile
// using typecasting numberShort = (short)numberLong; // this will compile
// byte is acceptable for a short value too numberShort = (byte)numberLong; // this will compile also

To typecast a value, simply specify the type enclosed in parentheses, writing it to the left of the value in question. It is important that you choose the correct data types when programming; otherwise you could lose values because the size of the value may be too large to be stored in the specified data type.

short numberShort = 2001;
byte numberByte = (byte)numberShort; // byte cannot store a positive integer value larger than 127

This code typecasts the value of numberShort to type byte, which will set the value of numberByte to a seemingly random number because 2001 is out of its storage range. The value of numberByte will actually set the value of the lowest 8 bits of numberShort. The value of numberShort is unaffected by the typecasting code; it remains equal to 2001. So when assigning a variable from a variable with a larger data type, be sure that the value is within the assigned variable's storage range; otherwise, use a larger data type in the first place. Sometimes it is simply more convenient to always use the int data type and not have to worry about typecasting and possible data loss. Let's look at an example for you to play around with:

public class UsingIntegers
 public static void main(String args[])
 { byte numberByte = 27;
 short numberShort = 2001;
 int numberInt = 50000;
 long numberLong = 3000000000L;
 // typecasting not needed as a long is larger than an int
 numberLong = numberInt;
 System.out.println("numberLong should equal " + numberLong);
 System.out.println("numberLong actually equals "+numberLong);
 // typecast numberShort's short value to a byte value
 numberByte = (byte)numberShort;
 System.out.println("numberByte should equal "+numberShort);
 System.out.println("numberByte actually equals "+numberByte);

This basic example makes two assignments as examples of converting values between integer data types. The first assignment works fine, but the second requires typecasting. Run the code and see what values are actually assigned from the conversions. The output from the program should look similar to this screen shot.

Java Click To expand

As you can see, the value of 50000 was assigned successfully from an int data type to a long data type, but the value of 2001 was not assigned successfully from a short data type to a byte data type. The actual answer of –47 was assigned because of the methods used to convert between the data types, which in this case involved ignoring relative information on storage bits that a byte value cannot contain. If the value was not 2001 but a value within the range that a byte could store, the assignment would have been successful.

Floating-Point Data Types

You should now understand how to declare and assign variables with specified data types. We can now look at two new data types, float and double, which are known as floating-point data types. Floating-point data types allow for more accurate storage than integers and store values with decimal places (for example, 0.25, 3.99, or –12.55555).

F-Point Type


Memory (bytes)


±3.4E+38 (Approx 7 significant figures)



±1.7E+308 (15 significant figures)


Declaring floating-point type variables is the same as declaring integer type variables.

float floatNumber;
double doubleNumber;

Assigning values for floating-point variables is the same also, but the value you assign can contain a decimal point.

double Pi = 3.141592653589793;

The assigned values do not require a decimal place, but if they are whole numbers, it sometimes makes your code clearer.

double flatPi = 3; // this will work double flatPi = 3.0; // or this will work too

As we already know, the default value for a whole number is of type int. The default value for a floating-point value is of type double, which means that numeric values assigned to variables of type float must be cast to a float value. This can be done either by adding the letter F (or preferred lowercase f) to the end of the value or by using the typecasting method that we saw earlier.

float floatNumber = 3.1415; // this will not compile
// add the 'f' letter to the end of the number float floatNumber = 3.1415f; // this will compile
// using typecasting float floatNumber = (float)3.1414; // this will compile also

Converting between Floating-Point Data Types

You can also use the typecasting method to convert from a double to a float variable, and there is no danger of getting drastically wrong conversions like with integers when converting from a double to a float data type, though some of the accuracy of the original double number could be lost when it is converted into a less accurate float value. There is no point typecasting a float value to a double because a double can store any value that a float can anyway. The following example,, illustrates this perfectly, declaring and setting the value of bigPi, a variable of type double, and then declaring a float variable, smallPi, and assigning its value to the value of Pi, typecasting the value to a float.

public class SliceOfPi
 public static void main(String args[])
 { double bigPi = 3.141592653589793;
 float smallPi = (float)bigPi; // using typecasting
 System.out.println("bigPi = " + bigPi);
 System.out.println("smallPi = " + smallPi);

When you compile this code, you should get output similar to this screen shot.

Java Click To expand

As you can see from Screenshot-6, the accuracy of bigPi's value when converted to a float value and assigned to the float variable smallPi is considerably less than its original double value. You may find it better to just use the double data type if you require very accurate floating-point data storage and are not overly concerned with memory usage.

Converting between Integers and Floating-Point Data Types

This is not as bad as it might sound; you just have to look at it logically. An integer cannot contain any values after a decimal place, so it will represent the value 3.14 as 3 and it will also represent the value 3.9 as 3, rounding the value down to the highest integer that is less than or equal to its float value by standard conversions. A floating-point variable can be assigned the value of an integer without any typecasting required.

int intNumber = 50000;
float floatNumber = intNumber;

Remember that you need to add the letter "f" to floating-point values in order to assign them to a float variable. However, this is not required if the value you specify is an integer value.

// no 'f' is required as integers convert straight to floating-point float floatNumber = 50000;

To convert from floating-point values to integer values, simply use typecasting.

float floatNumber = 50000.6f;
// using typecasting int intNumber = (int)floatNumber;

The value of the variable intNumber will be set to 50000, and the 0.6 will be chopped off; the original value is still stored in the floating-point variable floatNumber of course.