Learning outcome: Distinguish primitive and reference types, separate types from variables and objects, choose suitable data types, and understand default values.
Java is a statically typed language. Every variable has a declared type, and the compiler checks that values are used in ways compatible with those types.
Types that programmers can write in ordinary variable declarations fall into two main groups:
- Primitive types, which store simple values directly.
- Reference types, which store references to objects.
The Eight Primitive Types
Java has exactly eight primitive types.
In simple terms: A primitive holds the value itself, the way a matchbox holds a match. There are exactly eight kinds of box, and their sizes are fixed by the language rather than by the machine.
| Type | Family | Size | Holds / range | Default value for fields |
|---|---|---|---|---|
byte |
Integer | 1 byte | Whole numbers from -128 to 127 | 0 |
short |
Integer | 2 bytes | Whole numbers from -32,768 to 32,767 | 0 |
int |
Integer | 4 bytes | Whole numbers from -2^31 to 2^31 - 1 |
0 |
long |
Integer | 8 bytes | Whole numbers from -2^63 to 2^63 - 1; use L when a literal exceeds the int range |
0L |
float |
Floating-point | 4 bytes | Decimal values, about 6 to 7 significant digits | 0.0f |
double |
Floating-point | 8 bytes | Decimal values, about 15 to 16 significant digits | 0.0d |
char |
Character | 2 bytes | One UTF-16 code unit from 0 to 65,535 |
'\u0000' |
boolean |
Logical | JVM-dependent | true or false |
false |
The Java language does not define an exact storage size for boolean. It defines only the allowed values: true and false.
Choosing a Suitable Type
Use this practical guide:
| Need | Preferred type | Why |
|---|---|---|
| General whole numbers | int |
Default and efficient for most integer calculations. |
| Very large whole numbers | long |
Larger range than int. |
| General measurements and scientific decimals | double |
Default and more precise than float, but still approximate. |
| Memory-sensitive decimal arrays | float |
Smaller, but less precise. |
| One UTF-16 code unit | char |
Stores one 16-bit code unit; some Unicode characters require two. |
| True/false condition | boolean |
Used for decisions and logic. |
| Exact decimal values such as money | BigDecimal |
A reference type used when binary floating-point rounding is unacceptable. |
BigDecimal is the class java.math.BigDecimal. Construct exact decimal values from text, for example new BigDecimal("99.99"), rather than from an already approximate double value.
Example:
byte smallCounter = 100;
int age = 19;
long worldPopulation = 8_100_000_000L;
float piApprox = 3.14f;
double temperature = 36.75;
char grade = 'A';
boolean passed = true;
Reference Types
According to the Java Language Specification, Java SE 17, Section 4.3, Java has four kinds of reference types: class types, interface types, type variables, and array types. These are categories; names such as Student, Book, and Account are merely examples of user-defined class types. An enum declaration creates a specialised class type rather than a fifth reference-type category. Java also defines a special, unnamed null type for the null literal; programmers cannot declare a variable using that type.
In simple terms: A reference variable does not hold the object; it holds directions to it. Copying the variable copies the directions, not the house.
A reference variable conceptually stores a reference to an object or array rather than storing that object's contents inside the variable.
int count = 5; // primitive value
String name = "Aarav"; // reference to a String object
int[] scores = {80, 90, 95}; // reference to an array object
The four reference-type categories are:
| JLS category | Examples and explanation |
|---|---|
| Class type | Library classes such as String and Scanner, and any declared class such as Student, Book, or Account. An enum type such as DayOfWeek is a special class type. |
| Interface type | Runnable, Comparable |
| Type variable | T in class Box<T> or E in interface List<E> |
| Array type | int[], String[], Student[] |
User-Defined Classes Are Class Types
A class declaration introduces a new class type. Therefore, each of Student, Book, Account, Course, and the many other class names that programmers may declare can be a reference type. Student has no special status; it is used below only as one example.
class Student {
String name;
}
class StudentReferenceDemo {
public static void main(String[] args) {
Student learner = new Student();
learner.name = "Asha";
}
}
These terms refer to different things:
| Code or concept | What it is |
|---|---|
Student |
A class type, therefore a reference type |
learner |
A reference variable whose declared type is Student |
new Student() |
An expression that creates a Student object |
| the resulting object | A runtime instance of the Student class, not a separate category of data type |
The category is class type, not “Student type.” Student is one possible declared class type. Calling the object itself a “reference type” would also be imprecise: the class is the type, the variable holds a reference, and the object is an instance.
The default value for a reference field is null, which means the variable does not currently refer to an object. null is not an object and cannot be assigned to a primitive variable.
Arrays are reference types. They are covered in a dedicated topic that includes declaration, traversal, multidimensional arrays, and jagged arrays.
Primitive vs Reference Behaviour
Primitive assignment copies the value.
In simple terms: Assigning a primitive photocopies the value, so changing one copy leaves the other untouched. Assigning a reference hands over a second key to the same room.
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
System.out.println(b); // 20
Reference assignment copies the reference, not the object.
int[] first = {10, 20};
int[] second = first;
second[0] = 99;
System.out.println(first[0]); // 99
Both first and second refer to the same array object.
Default Values
Default values apply to fields: instance variables and static variables declared in a class. They do not apply to local variables declared inside a method.
In simple terms: Fields arrive like a form with the blanks pre-filled as zero. Local variables get no such courtesy, which is why the compiler refuses to read one before you have written to it.
public class DefaultsDemo {
int count; // field: defaults to 0
boolean active; // field: defaults to false
String name; // field: defaults to null
public void show() {
int localCount;
// System.out.println(localCount); // error: not initialised
}
}
| Variable kind | Default value? | Example |
|---|---|---|
| Instance field | Yes | int count; becomes 0 |
| Static field | Yes | static boolean ready; becomes false |
| Array element | Yes | Every element of new int[3] starts as 0 |
| Local variable | No | Must be assigned before use |
Worked Example
public class DataTypesDemo {
public static void main(String[] args) {
byte b = 100;
int count = 50000;
long worldPopulation = 8_100_000_000L;
float pi = 3.14f;
double temperature = 36.75;
char grade = 'A';
boolean passed = true;
System.out.println("byte : " + b);
System.out.println("int : " + count);
System.out.println("long : " + worldPopulation);
System.out.println("float : " + pi);
System.out.println("double : " + temperature);
System.out.println("char : " + grade);
System.out.println("boolean : " + passed);
}
}
Output:
byte : 100
int : 50000
long : 8100000000
float : 3.14
double : 36.75
char : A
boolean : true
Common Mistakes
| Mistake | Fix |
|---|---|
Forgetting L on a large integer literal |
Use a suffix such as 3_000_000_000L when the literal is outside the int range. |
Forgetting f for a float literal |
Use 3.14f. Without f, Java treats it as double. |
Confusing char and String |
Use 'A' for char, "A" for String. |
Assuming one char always represents one visible Unicode character |
A char is one UTF-16 code unit; some characters require a surrogate pair of two char values. |
| Using a local variable before assignment | Initialise it before reading it. |
Expecting 7 / 2 to produce 3.5 |
Two integers divide to an integer result. Casting is covered in the operators topic. |
Practice
Problem 1: Choose Types
Choose suitable Java types for:
- A student's age.
- A product price that must be represented exactly.
- A college name.
- A pass/fail flag.
- A single grade letter.
- The world population.
Problem 2: Predict Defaults
What are the field defaults?
public class Student {
int rollNo;
double percentage;
boolean placed;
String name;
}
Problem 3: Primitive or Reference
Classify each type:
int
String
double
int[]
boolean
Scanner
Quick Check
1. How many primitive types does Java have?
Java has eight primitive types: byte, short, int, long, float, double, char, and boolean.
2. What is the default value of an int field?
The default value of an int field is 0.
3. Does a local variable get a default value?
No. A local variable must be initialised before it is used, or the program will not compile.
4. What is the difference between char and String?
char stores one UTF-16 code unit and uses single quotes, such as 'A'. Some Unicode characters require two char values. String is a reference type representing a sequence of UTF-16 code units and uses double quotes, such as "A".
5. What does null mean?
null means a reference variable does not currently refer to any object.
6. What kind of types are introduced by declarations such as class Student {} and class Book {}?
Each declaration introduces a user-defined class type, and every class type is a reference type. Student and Book are examples, not separate reference-type categories.
Summary
Primitive variables hold primitive values; reference variables refer to objects or arrays. Java's four reference-type categories are class types, interface types, type variables, and array types. Declaring any class introduces a class type, while using new creates an object of that type. Fields receive default values, but local variables must be initialised before use. Choosing the right type makes programs clearer, safer, and easier to maintain.