Ch 2.4 Primitive Types
Java's 8 primitive data types can be broadly divided into 4 categories: boolean, character, integer, and floating-point types. In this section, we will look in detail at the characteristics and uses of each type.
Primitive Type Memory Size Visualization
1 byte | boolean | byte |
2 bytes | char | short |
4 bytes | int | float |
8 bytes | long | double |
1 byte = 8 bits
A bit can only hold two states: 0 or 1
1. Boolean Type: boolean
The boolean type can only hold two values: true and false. Its default value is false. Boolean variables are used to express logical states such as answers (yes/no), switches (on/off), and conditions (true/false).
According to the JVM specification, boolean is often processed as an int (4 bytes), but is treated as 1 byte in arrays. The exact size depends on the JVM implementation.
public class BooleanExample {
public static void main(String[] args) {
boolean isPowerOn = true;
boolean hasPermission = false;
boolean isAdult = (20 >= 18); // Assign the result of a conditional expression
boolean isEmpty = "".isEmpty(); // Assign the result of a method call
System.out.println("Power state: " + isPowerOn);
System.out.println("Has permission: " + hasPermission);
System.out.println("Is adult: " + isAdult);
System.out.println("Is empty string: " + isEmpty);
// Logical operations
System.out.println("AND: " + (isPowerOn && hasPermission)); // false
System.out.println("OR: " + (isPowerOn || hasPermission)); // true
System.out.println("NOT: " + (!isPowerOn)); // false
}
}
Output:
Power state: true
Has permission: false
Is adult: true
Is empty string: true
AND: false
OR: true
NOT: false
2. Character Type: char
The character type is used to store a single character and must be assigned by wrapping the character in single quotes ('). Internally, the Unicode integer value corresponding to the character is stored. Java's char is 2 bytes (16 bits) and supports Unicode in the range 0~65,535.
public class CharExample {
public static void main(String[] args) {
// Various ways to declare char (all equal 'A')
char ch1 = 'A'; // Directly specify the character
char ch2 = 65; // Specify by decimal integer (Unicode for A)
char ch3 = '\u0041'; // Unicode hexadecimal notation
System.out.println(ch1); // A
System.out.println(ch2); // A
System.out.println(ch3); // A
// char arithmetic
char next = (char)('A' + 1); // 'A'(65) + 1 = 66 = 'B'
System.out.println(next); // B
// Iterating the alphabet
for (char c = 'A'; c <= 'Z'; c++) {
System.out.print(c + " ");
}
System.out.println();
// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
// char -> int (check Unicode value)
int unicodeValue = 'A';
System.out.println("Unicode for A: " + unicodeValue); // 65
// Korean characters can also be stored as char (Unicode)
char korean = '가';
System.out.println("Unicode for 가: " + (int)korean); // 44032
}
}
char Escape Sequences
| Notation | Meaning | Unicode |
|---|---|---|
'\n' | Newline (Line Feed) | \u000A |
'\t' | Tab | \u0009 |
'\r' | Carriage Return | \u000D |
'\\' | Backslash | \u005C |
'\'' | Single Quote | \u0027 |
'\"' | Double Quote | \u0022 |
3. Integer Type: byte
byte uses 1 byte (8 bits) and stores integers in the range -128 ~ 127. Although the range is small, it is frequently used when handling binary data in file I/O and network communication.
public class ByteExample {
public static void main(String[] args) {
byte min = Byte.MIN_VALUE; // -128
byte max = Byte.MAX_VALUE; // 127
System.out.println("byte min: " + min);
System.out.println("byte max: " + max);
// Practical use: reading 1 byte at a time from a file (pseudo code)
byte[] fileData = {72, 101, 108, 108, 111}; // "Hello" ASCII
for (byte b : fileData) {
System.out.print((char) b); // H, e, l, l, o
}
System.out.println();
// Overflow demonstration
byte overflow = 127;
overflow++; // 127 + 1 = -128 (overflow!)
System.out.println("127 + 1 = " + overflow); // -128
}
}
Practical use cases for byte: image pixel data processing, file read/write streams, and network socket data transmission — typically used as a byte[] array.
4. Integer Type: short
short uses 2 bytes (16 bits) and stores values in the range -32,768 ~ 32,767. It has a smaller range than int so it saves memory, but since Java arithmetic is processed in int units by default, short values are converted to int during operations.
public class ShortExample {
public static void main(String[] args) {
short min = Short.MIN_VALUE; // -32768
short max = Short.MAX_VALUE; // 32767
System.out.println("short min: " + min);
System.out.println("short max: " + max);
// Note: result of short arithmetic is int
short a = 100;
short b = 200;
// short c = a + b; // Error! a+b result is int
int c = a + b; // OK
short d = (short)(a + b); // Store in short with explicit cast
System.out.println("100 + 200 = " + c); // 300
}
}
In practice, short is rarely used. The overhead of type conversion with int outweighs the memory savings. It is occasionally used in embedded systems or when interfacing with C libraries.
5. Integer Type: int (Most Important!)
int uses 4 bytes (32 bits) and stores values in the range of approximately -2.1 billion ~ 2.1 billion. It is the default integer type in Java — integer literals without a suffix are all treated as int. It is the most frequently used type.
public class IntExample {
public static void main(String[] args) {
int min = Integer.MIN_VALUE; // -2,147,483,648
int max = Integer.MAX_VALUE; // 2,147,483,647
System.out.println("int min: " + min);
System.out.println("int max: " + max);
System.out.printf("int max (2^31 - 1): %,d%n", max); // 2,147,483,647
// Common int usage
int year = 2024;
int dayOfYear = 365;
int totalMinutes = dayOfYear * 24 * 60;
System.out.println("Total minutes in a year: " + totalMinutes); // 525600
// Check binary representation
System.out.println("10 in binary: " + Integer.toBinaryString(10)); // 1010
System.out.println("255 in hex: " + Integer.toHexString(255)); // ff
System.out.println("8 in octal: " + Integer.toOctalString(8)); // 10
// Integer utility methods
System.out.println("Max of 100 and 200: " + Integer.max(100, 200)); // 200
System.out.println("Min of 100 and 200: " + Integer.min(100, 200)); // 100
System.out.println("String to int: " + Integer.parseInt("42")); // 42
}
}
6. Integer Type: long
long uses 8 bytes (64 bits) and stores values in the range of approximately -9 quadrillion ~ 9 quadrillion. Use it when dealing with large numbers that int cannot represent. long literals must have the L or l suffix (uppercase L is recommended).
public class LongExample {
public static void main(String[] args) {
long min = Long.MIN_VALUE; // -9,223,372,036,854,775,808
long max = Long.MAX_VALUE; // 9,223,372,036,854,775,807
System.out.println("long min: " + min);
System.out.println("long max: " + max);
// Practical use: timestamp (milliseconds)
long currentTime = System.currentTimeMillis(); // Milliseconds since Jan 1, 1970
System.out.println("Current timestamp (ms): " + currentTime);
// File size (in bytes)
long fileSize = 4_294_967_296L; // 4GB = 4 * 1024^3
System.out.printf("File size: %,d bytes%n", fileSize);
// Astronomical distance calculation
long lightYearInKm = 9_461_000_000_000L; // 1 light-year in km
long distanceToAndromeda = lightYearInKm * 2_537_000L; // Distance to Andromeda
System.out.printf("Distance to Andromeda: %e km%n", (double)distanceToAndromeda);
// Confirming int range overflow
// int overflow = 3_000_000_000; // Error! exceeds int max value
long safe = 3_000_000_000L; // OK with long
System.out.println("3 billion: " + safe);
}
}
Use long when dealing with large numbers such as timestamps, file sizes, population counts, and financial transaction amounts. In particular, the return type of System.currentTimeMillis() is long.
7. Floating-Point Type: float
float uses 4 bytes (32 bits) and provides approximately 7 decimal digits of precision. float literals must have the f or F suffix.
public class FloatExample {
public static void main(String[] args) {
float min = Float.MIN_VALUE; // Smallest positive value
float max = Float.MAX_VALUE; // Maximum value
System.out.println("float min positive: " + min); // 1.4E-45
System.out.println("float max: " + max); // 3.4028235E38
float pi = 3.141592f;
System.out.println("float PI: " + pi); // 3.141592
// Precision issue (approximately 7 digits)
float precise = 1.23456789f;
System.out.println("7-digit precision: " + precise); // 1.2345679 (8th digit rounded)
// Floating-point error
float result = 0.1f + 0.2f;
System.out.println("0.1 + 0.2 = " + result); // May not be exactly 0.3!
}
}
Floating-point precision problem: float and double represent decimals in binary, so some values (0.1, 0.3, etc.) cannot be represented exactly. Use BigDecimal when exact decimal arithmetic is required.
8. Floating-Point Type: double (Default Floating-Point Type)
double uses 8 bytes (64 bits) and provides approximately 15 decimal digits of precision. Decimal literals without a suffix are treated as double by default. It is the most commonly used floating-point type.
public class DoubleExample {
public static void main(String[] args) {
double min = Double.MIN_VALUE; // Smallest positive value
double max = Double.MAX_VALUE; // Maximum value
System.out.println("double min positive: " + min); // 4.9E-324
System.out.println("double max: " + max); // 1.7976931348623157E308
double pi = 3.14159265358979323846;
System.out.printf("PI (15 digits): %.15f%n", pi); // 3.141592653589793
// Special values
System.out.println("Positive infinity: " + Double.POSITIVE_INFINITY); // Infinity
System.out.println("Negative infinity: " + Double.NEGATIVE_INFINITY); // -Infinity
System.out.println("Not a number: " + Double.NaN); // NaN
System.out.println("0.0 / 0.0 = " + (0.0 / 0.0)); // NaN
// BigDecimal - for exact decimal arithmetic
java.math.BigDecimal bd1 = new java.math.BigDecimal("0.1");
java.math.BigDecimal bd2 = new java.math.BigDecimal("0.2");
java.math.BigDecimal sum = bd1.add(bd2);
System.out.println("BigDecimal 0.1 + 0.2 = " + sum); // 0.3 (exact!)
}
}
For financial calculations(banking, e-commerce payments, etc.), use BigDecimal instead of double. Floating-point errors in double can cause critical bugs in monetary calculations.
9. Min/Max Values of All Primitive Types at a Glance
public class AllLimits {
public static void main(String[] args) {
System.out.println("=== Integer Type Ranges ===");
System.out.printf("byte: %d ~ %d%n", Byte.MIN_VALUE, Byte.MAX_VALUE);
System.out.printf("short: %d ~ %d%n", Short.MIN_VALUE, Short.MAX_VALUE);
System.out.printf("int: %,d ~ %,d%n", Integer.MIN_VALUE, Integer.MAX_VALUE);
System.out.printf("long: %d ~ %d%n", Long.MIN_VALUE, Long.MAX_VALUE);
System.out.println("\n=== Floating-Point Ranges ===");
System.out.printf("float: %e ~ %e (precision: %d digits)%n",
Float.MIN_VALUE, Float.MAX_VALUE, 7);
System.out.printf("double: %e ~ %e (precision: %d digits)%n",
Double.MIN_VALUE, Double.MAX_VALUE, 15);
System.out.println("\n=== Other ===");
System.out.println("char min: " + (int)Character.MIN_VALUE); // 0
System.out.println("char max: " + (int)Character.MAX_VALUE); // 65535
}
}
Output:
=== Integer Type Ranges ===
byte: -128 ~ 127
short: -32768 ~ 32767
int: -2,147,483,648 ~ 2,147,483,647
long: -9223372036854775808 ~ 9223372036854775807
=== Floating-Point Ranges ===
float: 1.401298e-45 ~ 3.402823e+38 (precision: 7 digits)
double: 4.900000e-324 ~ 1.797693e+308 (precision: 15 digits)
=== Other ===
char min: 0
char max: 65535
10. Practical Example: Overflow Demonstration by Type
public class OverflowDemo {
public static void main(String[] args) {
System.out.println("=== byte overflow ===");
byte byteMax = Byte.MAX_VALUE; // 127
System.out.println("127: " + byteMax);
byteMax++;
System.out.println("127 + 1 = " + byteMax); // -128 (overflow!)
System.out.println("\n=== short overflow ===");
short shortMax = Short.MAX_VALUE; // 32767
System.out.println("32767: " + shortMax);
shortMax++;
System.out.println("32767 + 1 = " + shortMax); // -32768 (overflow!)
System.out.println("\n=== int overflow ===");
int intMax = Integer.MAX_VALUE; // 2147483647
System.out.printf("%,d%n", intMax);
intMax++;
System.out.printf("%,d (overflow!)%n", intMax); // -2147483648
System.out.println("\n=== Preventing overflow with long ===");
long safeLong = (long)Integer.MAX_VALUE + 1;
System.out.printf("%,d (safe)%n", safeLong); // 2147483648
System.out.println("\n=== float precision loss ===");
float f = 0.1f;
float sum = 0.0f;
for (int i = 0; i < 10; i++) {
sum += f;
}
System.out.println("0.1 * 10 = " + sum); // 1.0000001 (error!)
System.out.println("\n=== Improved with double ===");
double d = 0.1;
double dsum = 0.0;
for (int i = 0; i < 10; i++) {
dsum += d;
}
System.out.println("0.1 * 10 = " + dsum); // 1.0 (more accurate but not perfect)
}
}
Summary
| Type | Size | Characteristics | Primary Use Cases |
|---|---|---|---|
boolean | 1 bit~1 byte | true/false | Conditions, flags |
char | 2 bytes | Unicode character | Single character processing |
byte | 1 byte | -128~127 | File/network I/O |
short | 2 bytes | -32768~32767 | Rarely used |
int | 4 bytes | Default integer type | General integer arithmetic |
long | 8 bytes | Very large integers | Timestamps, file sizes |
float | 4 bytes | 7-digit decimal precision | Graphics, physics |
double | 8 bytes | 15-digit decimal precision | General floating-point arithmetic |