Skip to main content

Ch 2.2 Variable Types

Java is a strongly typed language that requires you to specify the type of data to be stored in advance. The type of a variable determines how the value is stored and interpreted.

1. Primitive Types vs Reference Types​

Java's data types are divided into two main categories.

CategoryPrimitive TypeReference Type
Stored contentStores the actual value directlyStores the memory address of an object
Memory locationStackHeap
Varieties8 types (int, double, etc.)Unlimited (String, arrays, classes, etc.)
Default valueFixed per type (0, false, etc.)null
SizeFixed per type (1~8 bytes)Varies by JVM (4 or 8 byte address)
Primitive variable (Stack)          Reference variable (Stack β†’ Heap)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ int age=25 β”‚ β”‚ String name │──────▢│ "Alice" (Heap) β”‚
β”‚ age: [25] β”‚ β”‚ name: [addr]β”‚ β”‚ (actual object) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
note

Primitive values are stored directly on the stack for fast access. Reference types store the address of a heap object on the stack.

2. All 8 Primitive Types​

There are exactly 8 primitive types, categorized as boolean, character, integer, and floating-point.

CategoryTypeSizeRangeDefaultWrapper Class
Booleanboolean1 bit (JVM-dependent)true / falsefalseBoolean
Characterchar2 bytes'\u0000' ~ '\uFFFF' (0 ~ 65,535)'\u0000'Character
Integerbyte1 byte-128 ~ 1270Byte
Integershort2 bytes-32,768 ~ 32,7670Short
Integerint4 bytes-2,147,483,648 ~ 2,147,483,6470Integer
Integerlong8 bytes-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,8070LLong
Floating-pointfloat4 bytesΒ±3.4 Γ— 10^38 (7 decimal digits)0.0fFloat
Floating-pointdouble8 bytesΒ±1.8 Γ— 10^308 (15 decimal digits)0.0dDouble
public class AllPrimitiveTypes {
public static void main(String[] args) {
boolean isJavaFun = true; // boolean
char letter = 'J'; // character
byte tinyNum = 100; // integer (small range)
short smallNum = 30000; // integer (medium range)
int normalNum = 2000000; // integer (default, most commonly used)
long bigNum = 9_000_000_000L; // integer (large range, L suffix required)
float floatNum = 3.14f; // floating-point (f suffix required)
double doubleNum = 3.141592653; // floating-point (default, high precision)

System.out.println("boolean: " + isJavaFun);
System.out.println("char: " + letter);
System.out.println("byte: " + tinyNum);
System.out.println("short: " + smallNum);
System.out.println("int: " + normalNum);
System.out.println("long: " + bigNum);
System.out.println("float: " + floatNum);
System.out.println("double: " + doubleNum);
}
}

3. Literals and Notation​

A literal is a fixed value written directly in code. Notation varies by type.

Integer Literals​

int decimal = 100;          // Decimal (default)
int binary = 0b01100100; // Binary (0b prefix)
int octal = 0144; // Octal (0 prefix)
int hex = 0x64; // Hexadecimal (0x prefix)

long bigLong = 100L; // long literal (L or l suffix, uppercase recommended)
long billion = 1_000_000_000L; // Underscores for readability (Java 7+)

// All 4 above hold the same value (100)
System.out.println(decimal == binary); // true
System.out.println(binary == octal); // true
System.out.println(octal == hex); // true

Floating-Point Literals​

double d1 = 3.14;       // double (default, no suffix)
double d2 = 3.14d; // double (explicit d suffix)
double d3 = 3.14e2; // Scientific notation = 314.0
float f1 = 3.14f; // float (f suffix required!)
float f2 = 3.14F; // float (F also works)

// 3.14 is a double by default, so float requires the f suffix
// float f3 = 3.14; // Error! possible lossy conversion from double to float

Character Literals​

char c1 = 'A';          // Character literal (single quotes)
char c2 = 65; // Specify character by integer value (A = 65)
char c3 = '\u0041'; // Direct Unicode notation (A)
char c4 = '\n'; // Special character (newline)
char c5 = '\t'; // Special character (tab)

// Escape sequences
// \' single quote
// \" double quote
// \\ backslash
// \n newline
// \t tab
// \r carriage return

boolean Literals​

boolean b1 = true;
boolean b2 = false;
boolean b3 = (10 > 5); // Conditional expressions can also be used as boolean values

4. Reference Types: String, Arrays, Classes, Interfaces​

Reference types include everything except the 8 primitive types.

// String - most commonly used reference type
String greeting = "Hello, Java!";
String empty = ""; // Empty string
String nullStr = null; // References no object

// Arrays
int[] scores = {95, 88, 72, 100};
String[] names = {"Alice", "Bob", "Charlie"};

// Classes (user-defined)
// Student student = new Student("Alice", 20);

5. Special Treatment of String​

String is a class but can be created with a literal (without new), just like a primitive. Java maintains a special memory space called the String Constant Pool for frequently used strings.

public class StringComparison {
public static void main(String[] args) {
// Literal method: uses String Pool (same content shares same object)
String s1 = "hello";
String s2 = "hello";

// new keyword: creates a new object every time (stored separately in heap)
String s3 = new String("hello");
String s4 = new String("hello");

// == : compares addresses (references)
System.out.println(s1 == s2); // true (same Pool object)
System.out.println(s1 == s3); // false (different objects)
System.out.println(s3 == s4); // false (different new objects)

// .equals() : compares content (values) <- always use this for strings!
System.out.println(s1.equals(s2)); // true
System.out.println(s1.equals(s3)); // true
System.out.println(s3.equals(s4)); // true
}
}
warning

Always use .equals() when comparing Strings! Using == compares addresses and can produce unexpected results.

6. null and NullPointerException​

null is the state where a reference variable points to no object.

public class NullExample {
public static void main(String[] args) {
String name = null; // name points to nothing
System.out.println(name); // null (printing is fine)

// Calling a method on a null variable causes NullPointerException!
try {
int length = name.length(); // Error!
} catch (NullPointerException e) {
System.out.println("NullPointerException occurred!");
System.out.println("Cannot call methods on a null variable.");
}

// How to check for null
if (name != null) {
System.out.println("Length: " + name.length());
} else {
System.out.println("name is null.");
}
}
}
tip

Since Java 14+, NullPointerException messages have been improved to clearly indicate which variable was null.

7. Wrapper Classes​

Each primitive type has a corresponding wrapper class. These are used when a primitive needs to be treated as an object (collections, generics, etc.).

public class WrapperExample {
public static void main(String[] args) {
// Primitive -> Wrapper class (Boxing)
int primitiveInt = 42;
Integer wrappedInt = Integer.valueOf(primitiveInt); // Explicit Boxing
Integer autoBoxed = primitiveInt; // Auto-Boxing (Java 5+)

// Wrapper class -> Primitive (Unboxing)
int unboxed = wrappedInt.intValue(); // Explicit Unboxing
int autoUnboxed = wrappedInt; // Auto-Unboxing

// Useful wrapper class methods
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Integer.toBinaryString(255)); // 11111111
System.out.println(Integer.parseInt("100")); // 100 (String -> int)
System.out.println(Double.parseDouble("3.14")); // 3.14 (String -> double)
}
}

8. Object Class β€” The Root of All Classes​

Every Java class automatically inherits from Object. It sits at the top of Java's class hierarchy.

Object
β”œβ”€β”€ String
β”œβ”€β”€ Integer
β”œβ”€β”€ ArrayList
β”œβ”€β”€ Scanner
└── (all user-defined classes)
public class ObjectExample {
public static void main(String[] args) {
// Object type can hold any reference variable
Object obj1 = "Hello"; // String as Object
Object obj2 = 42; // Integer as Object (autoboxing)
Object obj3 = new int[]{1, 2, 3}; // Array as Object

// toString() - available on all objects (inherited from Object)
System.out.println(obj1.toString()); // Hello
System.out.println(obj2.toString()); // 42
}
}

9. Constants and Numeric Literal Readability​

public class LiteralReadability {
// Constants are typically declared as static final at class level
static final double PI = 3.14159265358979;
static final int SECONDS_PER_DAY = 24 * 60 * 60; // 86400

public static void main(String[] args) {
// Java 7+ numeric underscore notation for readability
long population = 8_000_000_000L; // 8 billion
int creditCardNum = 1234_5678_9012_3456; // card number
double avogadro = 6.022_140_76e23; // Avogadro's number

System.out.println("World population: " + population);
System.out.println("Seconds per day: " + SECONDS_PER_DAY);
System.out.println("Pi: " + PI);
}
}

10. Practical Example: Declaring and Printing Various Type Variables​

public class TypesDemo {
public static void main(String[] args) {
// Personal information
String name = "Java Lee";
int age = 28;
char gender = 'M';
boolean isMarried = false;

// Physical information
double height = 175.5;
float weight = 68.3f;

// Financial information
long salary = 3_500_000L; // Monthly salary
double taxRate = 0.033; // Tax rate 3.3%

// Calculations
long tax = (long)(salary * taxRate);
long netSalary = salary - tax;

// Output
System.out.println("===== Employee Info =====");
System.out.printf("Name: %s%n", name);
System.out.printf("Age: %d%n", age);
System.out.printf("Gender: %c%n", gender);
System.out.printf("Married: %b%n", isMarried);
System.out.printf("Height: %.1f cm%n", height);
System.out.printf("Weight: %.1f kg%n", weight);
System.out.printf("Salary: %,d%n", salary);
System.out.printf("Tax (%.1f%%): %,d%n", taxRate * 100, tax);
System.out.printf("Net Salary: %,d%n", netSalary);
}
}

Output:

===== Employee Info =====
Name: Java Lee
Age: 28
Gender: M
Married: false
Height: 175.5 cm
Weight: 68.3 kg
Salary: 3,500,000
Tax (3.3%): 115,500
Net Salary: 3,384,500

Summary​

  • Java data types: 8 primitive types+ reference types (unlimited)
  • Primitives: value stored directly on stack, 8 types (boolean, char, byte, short, int, long, float, double)
  • Reference types: address of heap object stored on stack (String, arrays, classes, etc.)
  • Always use .equals() for String comparison(== compares addresses)
  • null: initial state of reference variables, causes NPE when methods are called
  • Wrapper classes: object versions of primitives (Integer, Double, etc.)
  • All classes inherit from Object