› Module 2: Data Types, Variables & Operators › 2.2 Data Types: Primitive vs Reference
M O D U L E

Module 2: Data Types, Variables & Operators

Primitive vs reference type memory models, explicit type casting, constants, operators, and the identity vs equality pitfall.

2.1 Keywords and Identifiers

Java reserves roughly 50 keywords — reserved vocabulary words like class, public, static, void, if, for, extends, and implements that have fixed syntactic meanings built into the compiler grammar. Keywords cannot be used as variable, method, or class names.

Identifiers are user-defined names for variables, methods, classes, and packages. While the compiler permits any sequence of alphanumeric characters starting with a letter, underscore (_), or dollar sign ($), the standard Java community adheres to strict naming conventions:

  • Classes & Interfaces: PascalCase where every word starts with a capital letter (e.g. BankAccount, StudentManager).
  • Variables & Methods: camelCase where the first letter is lowercase and subsequent words are capitalized (e.g. totalBalance, calculateInterest()).
  • Constants: UPPER_SNAKE_CASE (e.g. MAX_CAPACITY, DEFAULT_TIMEOUT).
Case Sensitivity:

Java is strictly case-sensitive. The identifiers age, Age, and AGE refer to three distinct, unrelated variables.

💡 Placement & Interview Deep-Dive

  • Are true, false, and null keywords in Java? Technically, NO! In the Java Language Specification (JLS), true and false are boolean literals, and null is a null literal. However, they are strictly reserved and CANNOT be used as identifiers.
  • Which keywords are reserved in Java but currently unused? const and goto are reserved keywords in Java, but they have no function. Using them causes a compile-time syntax error. Java reserved them to prevent programmers with C/C++ backgrounds from introducing unstructured code.

2.2 Data Types: Primitive vs Reference

Every value in Java belongs to one of two fundamentally distinct families: Primitive Types and Reference Types. This architectural distinction dictates memory allocation, equality evaluation, and argument passing.

The 8 Primitive Data Types

Primitives represent raw scalar values stored directly in memory (typically on the Call Stack for local variables). They are not objects, have no methods, and cannot be null:

Type Size Range / Details Example Declaration
byte 1 byte (8 bits) -128 to 127 byte b = 100;
short 2 bytes (16 bits) -32,768 to 32,767 short s = 5000;
int 4 bytes (32 bits) -2,147,483,648 to 2,147,483,647 int age = 25;
long 8 bytes (64 bits) -9 × 1018 to 9 × 1018 (use 'L' suffix) long distance = 100000L;
float 4 bytes (32 bits) ~6-7 decimal digits (IEEE 754, use 'f' suffix) float rate = 5.75f;
double 8 bytes (64 bits) ~15-16 decimal digits (default floating point) double pi = 3.14159;
char 2 bytes (16 bits) 0 to 65,535 (16-bit Unicode characters) char grade = 'A';
boolean 1 bit (conceptually) true or false (not integers!) boolean isValid = true;

Reference Data Types

Reference types include classes, interfaces, arrays, and String. A reference variable does not hold the object's data directly; instead, it holds a memory reference (address) pointing to the object allocated on the Heap.

Java Data Types Primitive (8 types) byte, short, int, long, float, double, char, boolean Reference (Non-primitive) class, interface, array, String Primitives store values directly; reference types store an address on the heap.
Figure 2.2 — Java's two-tier type system: primitives vs. reference types.

💡 Placement & Interview Deep-Dive

  • Why is char 2 bytes in Java but 1 byte in C? C was designed around 7-bit ASCII, requiring only 1 byte. Java was designed for global internationalization, adopting 16-bit Unicode (UTF-16 code units) from day one so it can represent characters in Latin, Cyrillic, Chinese, Arabic, Devanagari, and more.
  • What is the default value of local variables vs instance variables? Instance and static fields are automatically initialized to default zero values (0, 0.0, false, null) upon object allocation. Local variables in methods receive NO default value; attempting to read an uninitialized local variable causes a compile-time error.

2.3 Variables, Type Casting, and Constants

Java is a strictly, statically-typed language. Every variable must have an explicit data type declared at compile-time: int x = 10; guarantees that x can only hold 32-bit signed integers. Assigning an incompatible type (like a String) fails compilation immediately.

Widening vs Narrowing Casting

Type conversion occurs in two forms:

  • Widening Casting (Implicit / Automatic): Converting a smaller data type to a larger data type size: byte → short → int → long → float → double. Because the target type can represent a strictly larger numeric range without precision loss, Java converts it automatically:
    int num = 42;
    double d = num; // Automatic widening: 42.0
  • Narrowing Casting (Explicit / Manual): Converting a larger data type to a smaller data type. Because information can be lost (overflow or truncation), Java forces the developer to write an explicit cast operator:
    double pi = 3.99;
    int truncated = (int) pi; // Explicit narrowing: 3 (NOT rounded, strictly truncated)

The final Keyword for Constants

Applying final to a variable prevents its value from being reassigned after initialization:

final double PI = 3.141592653589793;
// PI = 3.0; // COMPILE ERROR: cannot assign a value to final variable PI

💡 Placement & Interview Deep-Dive

  • The Binary Arithmetic Promotion Trap: Consider the following snippet:
    byte a = 10;
    byte b = 20;
    // byte c = a + b; // COMPILE ERROR! Type mismatch: cannot convert from int to byte
    Why? In Java, arithmetic operators (+, -, *, /) automatically promote operands smaller than int (i.e. byte and short) to int before evaluating the operation! Therefore, a + b yields an int, which cannot be assigned back to a byte without an explicit cast: byte c = (byte)(a + b);.
  • Can a final reference object's fields be modified? YES! final guarantees only that the reference pointer cannot be reassigned to a new object. The internal fields of the referenced object can still be mutated freely unless the object class itself is designed as immutable.

2.4 Operators and Expressions

Java provides the standard C-family operators: Arithmetic (+, -, *, /, %), Relational (==, !=, >, <, >=, <=), Logical (&&, ||, !), Assignment (=, +=, -=), Increment/Decrement (++, --), and Bitwise (&, |, ^, ~, <<, >>, >>>).

The Fundamental Trap: == vs .equals()

In Java, when you use == on reference types, it does NOT compare the internal contents of the objects. It evaluates Reference Identity — checking whether both variables point to the exact same physical heap memory address.

String a = new String("hi");
String b = new String("hi");

System.out.println(a == b);      // false (different heap memory addresses)
System.out.println(a.equals(b)); // true  (identical character sequence)
KEY TERM: == vs .equals()

== compares whether two reference variables point to the same object in memory (identity). .equals() compares the actual content of the objects. Primitives, by contrast, are always safely compared with ==, since they hold values directly rather than references.

💡 Placement & Interview Deep-Dive

  • What is the difference between >> and >>> in Java? >> is the signed (arithmetic) right shift: it preserves the sign bit (MSB), shifting in 1s if negative and 0s if positive. >>> is the unsigned (logical) right shift unique to Java: it always shifts in 0s from the left regardless of the operand's sign.
  • Short-circuiting vs Non-short-circuiting: && and || are short-circuit logical operators: if the first operand suffices to determine the result (e.g. false && func()), the second operand is never evaluated. & and | force evaluation of both sides, which can cause unexpected NullPointerException if used incorrectly!
MODULE COMPREHENSIVE QUIZ

Module 2 Final Quiz

Test your understanding across all 4 topics of this module with interview-grade questions, tricky edge cases, and code output predictions.

Take Module 2 Final Quiz →
Yukti Mascot