02 - Variables, Data Types, and Operators
A complete beginner-to-advanced guide to Java's type system and operators, aligned with the Oracle Certified Professional: Java SE 21 Developer (1Z0-830) exam objectives.
Table of Contents
- Primitive Types
- Literals & Number Formats
- Wrapper Classes
- Autoboxing & Unboxing
- The
varKeyword - Type Promotion (Widening)
- Type Casting (Narrowing)
- Numeric Promotion in Expressions
- Strings
- StringBuilder
- Java Operators
- Equality:
==vs.equals() - Java 21 Notes
- Certification Traps
- Common Mistakes
- Interview Questions
- Quick Revision Notes
- One-Page Cheat Sheet
1. Primitive Types
Java has exactly 8 primitive types. They store actual values directly (not references) and are the building blocks of all data.
| Type | Category | Size | Range | Default | Example |
|---|---|---|---|---|---|
byte | Integer | 8-bit | -128 to 127 | 0 | byte b = 100; |
short | Integer | 16-bit | -32,768 to 32,767 | 0 | short s = 1000; |
int | Integer | 32-bit | ~ -2.1B to 2.1B | 0 | int i = 42; |
long | Integer | 64-bit | ~ -9.2E18 to 9.2E18 | 0L | long l = 99L; |
float | Floating | 32-bit | ~6-7 decimal digits | 0.0f | float f = 3.14f; |
double | Floating | 64-bit | ~15 decimal digits | 0.0 | double d = 3.14; |
char | Character | 16-bit | 0 to 65,535 (Unicode) | '\u0000' | char c = 'A'; |
boolean | Logical | JVM-dependent | true / false | false | boolean ok = true; |
Key Points
- Defaults apply only to fields (instance/static). Local variables have no default and must be initialized.
charis unsigned (0–65535); the other integral types are signed.booleancannot be cast to/from any numeric type.boolean b = (boolean) 1;is illegal.byteandshortare auto-promoted tointin arithmetic.
char c = 'A';
int code = c; // 65 (char -> int widening)
System.out.println(code);
long big = 10_000_000_000L; // needs L; without it = compile error (too big for int)
2. Literals & Number Formats
| Literal | Example | Notes |
|---|---|---|
| Decimal | int x = 100; | Base 10. |
| Binary (Java 7+) | int b = 0b1010; | Prefix 0b. = 10 |
| Octal | int o = 010; | Prefix 0. = 8 |
| Hexadecimal | int h = 0xFF; | Prefix 0x. = 255 |
| Underscores (Java 7+) | int m = 1_000_000; | Readability only. |
long suffix | long l = 100L; | L (or l). |
float suffix | float f = 3.14f; | f (or F) required. |
double suffix | double d = 3.14d; | d optional (default). |
char | char c = '\u0041'; | Unicode escape = 'A'. |
Underscore Rules (Trap)
int valid = 1_000_000; // OK
int valid2 = 0b1010_0101; // OK
// int bad1 = _1000; // ERROR: cannot start with _
// int bad2 = 1000_; // ERROR: cannot end with _
// int bad3 = 0x_FF; // ERROR: not next to prefix
// double bad4 = 3._14; // ERROR: not next to decimal point
Rule: an underscore must be between two digits — never at the start, end, next to a decimal point, or next to a radix prefix.
3. Wrapper Classes
Each primitive has a corresponding wrapper class — an object form used in collections, generics, and when null is needed.
| Primitive | Wrapper |
|---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Creating Wrappers
Integer a = Integer.valueOf(10); // preferred (uses cache)
Integer b = 10; // autoboxing (also uses valueOf)
int x = a.intValue(); // explicit unboxing
int y = a; // auto-unboxing
// Integer c = new Integer(10); // DEPRECATED since Java 9, removed later
Useful Wrapper Methods
int p = Integer.parseInt("123"); // String -> int (primitive)
Integer q = Integer.valueOf("123"); // String -> Integer (object)
String s = Integer.toString(255); // "255"
String hex = Integer.toHexString(255); // "ff"
int max = Integer.MAX_VALUE; // 2147483647
boolean digit = Character.isDigit('5'); // true
parseXxxreturns a primitive;valueOfreturns a wrapper object. This distinction is a classic exam point.
The Integer Cache (Critical Trap)
Wrapper objects for Integer, Short, Byte, Long, and Character in the range -128 to 127 are cached and reused.
Integer a = 127, b = 127;
System.out.println(a == b); // true (same cached object)
Integer c = 128, d = 128;
System.out.println(c == d); // false (new objects, outside cache)
System.out.println(c.equals(d)); // true (value comparison)
Always compare wrapper values with
.equals(), not==.
4. Autoboxing & Unboxing
- Autoboxing: automatic conversion of a primitive → wrapper.
- Unboxing: automatic conversion of a wrapper → primitive.
List<Integer> list = new ArrayList<>();
list.add(5); // autoboxing: int 5 -> Integer
Integer obj = 10; // autoboxing
int prim = obj; // unboxing
int sum = obj + 5; // unboxing, add, (result is int)
The NullPointerException Trap
Integer value = null;
int x = value; // NullPointerException at runtime (unboxing null!)
Unboxing a null wrapper throws NPE — a very common exam and real-world bug.
No Two-Step Conversions (Trap)
Autoboxing does not combine with widening in one step:
Integer i = 5; // OK: int -> Integer (boxing)
// Long l = 5; // ERROR: int -> Long needs widen THEN box (2 steps)
long l1 = 5; // OK: int -> long (widening only)
Long l2 = 5L; // OK: long -> Long (boxing only)
Rule: the compiler will do widening OR boxing, but not both automatically in a single assignment.
5. The var Keyword
var (Java 10+) lets the compiler infer the type of a local variable from its initializer.
var name = "Java"; // String
var count = 10; // int
var price = 9.99; // double
var list = new ArrayList<String>(); // ArrayList<String>
Rules Table
| Rule | Example | Valid? |
|---|---|---|
| Local variables only | var x = 5; inside method | ✅ |
| Must have initializer | var x; | ❌ |
Cannot be null alone | var x = null; | ❌ |
| Not for fields | class C { var x = 5; } | ❌ |
| Not for method params | void m(var x) | ❌ |
| Not for return types | var m() {...} | ❌ |
OK in for loops | for (var i = 0; ...) | ✅ |
| Enhanced for | for (var s : list) | ✅ |
Important Subtleties
var x = 10; // int (NOT Integer)
var y = 10L; // long
var z = 'c'; // char
var d = 3.14; // double (not float)
var arr = new int[]{1, 2, 3}; // OK: int[]
// var bad = {1, 2, 3}; // ERROR: array initializer needs explicit type
varis a reserved type name, not a keyword — so you could name a method or variablevar, but you should not.
6. Type Promotion (Widening)
Widening = converting a smaller type to a larger type. It happens automatically because no data is lost.
Widening Path
byte -> short -> int -> long -> float -> double
^
char -----+ (char widens to int and beyond)
int i = 100;
long l = i; // automatic widening
double d = l; // automatic widening
float f = 100; // int -> float automatic (even though float is "smaller" in bits)
| From | Widens automatically to |
|---|---|
byte | short, int, long, float, double |
short | int, long, float, double |
char | int, long, float, double |
int | long, float, double |
long | float, double |
float | double |
Note:
long -> floatandint -> floatare widening (allowed automatically) even though precision can be lost — the magnitude range is larger.
7. Type Casting (Narrowing)
Narrowing = converting a larger type to a smaller type. You must do it explicitly with a cast because data may be lost.
double d = 9.99;
int i = (int) d; // 9 (decimal truncated, not rounded)
long l = 130;
byte b = (byte) l; // -126 (overflow wraps around!)
int big = 300;
byte b2 = (byte) big; // 44 (300 % 256 path -> overflow)
Overflow Behavior
byte b = (byte) 128; // -128 (wraps)
char c = (char) -1; // 65535 (char is unsigned)
Compound Assignment Hides a Cast (Trap)
byte b = 10;
// b = b + 5; // ERROR: b + 5 is int, cannot assign to byte
b += 5; // OK: compound operators include an IMPLICIT cast
System.out.println(b); // 15
+=,-=,*=,/=automatically cast the result back to the left-hand type. This is a favorite exam trap.
8. Numeric Promotion in Expressions
When evaluating arithmetic, Java promotes operands following these rules:
byte,short,charare promoted tointbefore any arithmetic.- If either operand is
long, the result islong. - If either is
float, the result isfloat. - If either is
double, the result isdouble.
byte a = 10, b = 20;
// byte c = a + b; // ERROR: a + b is int
int c = a + b; // OK: 30
char x = 'A'; // 65
int sum = x + 1; // 66 (char promoted to int)
System.out.println('A' + 'B'); // 131 (NOT "AB" — both promoted to int)
System.out.println("" + 'A' + 'B'); // "AB" (String concatenation)
Integer Division & Modulo Traps
System.out.println(5 / 2); // 2 (integer division)
System.out.println(5.0 / 2); // 2.5 (one double -> double result)
System.out.println(5 % 2); // 1
System.out.println(-7 % 3); // -1 (sign follows the dividend)
System.out.println(1 / 0); // ArithmeticException: / by zero
System.out.println(1.0 / 0); // Infinity (no exception for double!)
System.out.println(0.0 / 0.0); // NaN
9. Strings
A String is an immutable sequence of characters. Once created, its value cannot change — every "modification" creates a new object.
String Pool
String literals are stored in a special memory area called the String Pool (interned), so identical literals share one object.
String a = "hello";
String b = "hello";
System.out.println(a == b); // true (same pooled object)
String c = new String("hello");
System.out.println(a == c); // false (new object on heap)
System.out.println(a.equals(c)); // true (same characters)
System.out.println(a == c.intern()); // true (intern() returns pooled ref)
Diagram: Pool vs Heap
String Pool (interned) Heap
+----------------------+ +----------------------+
| "hello" <--- a, b | | "hello" <--- c |
+----------------------+ +----------------------+
^ |
+----- c.intern() -------------+
Immutability Trap
String s = "Java";
s.concat(" 21"); // creates new String, but result is DISCARDED
System.out.println(s); // "Java" (unchanged!)
s = s.concat(" 21"); // reassign to capture the new String
System.out.println(s); // "Java 21"
Common String Methods
String s = "Hello World";
s.length(); // 11
s.charAt(0); // 'H'
s.substring(0, 5); // "Hello"
s.indexOf("World"); // 6
s.toUpperCase(); // "HELLO WORLD"
s.replace("o", "0"); // "Hell0 W0rld"
s.trim(); // removes leading/trailing whitespace
s.strip(); // Unicode-aware trim (Java 11+)
s.isBlank(); // true if empty or only whitespace (Java 11+)
s.repeat(3); // repeats string (Java 11+)
"a,b,c".split(","); // ["a", "b", "c"]
Text Blocks (Java 15+)
String json = """
{
"name": "Java",
"version": 21
}
""";
+ Concatenation Rules
System.out.println(1 + 2 + "x"); // "3x" (left-to-right: 1+2=3, then +"x")
System.out.println("x" + 1 + 2); // "x12" (string first, so all concatenated)
10. StringBuilder
StringBuilder is a mutable sequence of characters. Use it when you need to build/modify strings repeatedly (e.g., in loops) — it avoids creating many throwaway String objects.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // "Hello World"
sb.insert(0, ">> "); // ">> Hello World"
sb.reverse(); // reverses in place
sb.delete(0, 3); // remove chars [0,3)
sb.replace(0, 5, "Hi"); // replace range
sb.length(); // current length
String result = sb.toString();
String vs StringBuilder vs StringBuffer
| Feature | String | StringBuilder | StringBuffer |
|---|---|---|---|
| Mutable? | ❌ No | ✅ Yes | ✅ Yes |
| Thread-safe? | ✅ (immutable) | ❌ No | ✅ Yes (synchronized) |
| Performance | Slow for many edits | Fast | Slower than Builder |
| Use when | Fixed text | Single-thread building | Multi-thread building |
Identity Trap
StringBuilder sb1 = new StringBuilder("hi");
StringBuilder sb2 = new StringBuilder("hi");
System.out.println(sb1 == sb2); // false
System.out.println(sb1.equals(sb2)); // false! (no equals override -> uses ==)
System.out.println(sb1.toString().equals(sb2.toString())); // true
StringBuilderdoes NOT overrideequals()— comparing two builders with.equals()compares references, not contents.
11. Java Operators
Operator Categories
| Category | Operators |
|---|---|
| Arithmetic | + - * / % |
| Unary | + - ++ -- ! ~ |
| Relational | < > <= >= == != |
| Logical (short-circuit) | && || |
| Bitwise / non-short-circuit | & | ^ ~ |
| Shift | << >> >>> |
| Assignment | = += -= *= /= %= ... |
| Ternary | ? : |
| Type comparison | instanceof |
Precedence (High → Low, simplified)
1. Postfix expr++ expr--
2. Unary ++expr --expr + - ! ~
3. Multiplicative * / %
4. Additive + -
5. Shift << >> >>>
6. Relational < > <= >= instanceof
7. Equality == !=
8. Bitwise AND &
9. Bitwise XOR ^
10. Bitwise OR |
11. Logical AND &&
12. Logical OR ||
13. Ternary ?:
14. Assignment = += -= ...
Pre vs Post Increment (Trap)
int i = 5;
System.out.println(i++); // 5 (use then increment) -> i is now 6
System.out.println(++i); // 7 (increment then use)
int a = 1;
int b = a++ + ++a; // 1 + 3 = 4 ; a ends at 3
System.out.println(b); // 4
Short-Circuit vs Non-Short-Circuit
int[] arr = null;
if (arr != null && arr.length > 0) { } // safe: && stops if left is false
// if (arr != null & arr.length > 0) {} // NPE: & evaluates BOTH sides
| Operator | Evaluates right side? |
|---|---|
&& | Only if left is true |
|| | Only if left is false |
& / | | Always (both sides) |
Bitwise & Shift Examples
System.out.println(5 & 3); // 1 (0101 & 0011 = 0001)
System.out.println(5 | 3); // 7 (0101 | 0011 = 0111)
System.out.println(5 ^ 3); // 6 (XOR)
System.out.println(~5); // -6 (bitwise NOT)
System.out.println(1 << 3); // 8 (left shift = *2^3)
System.out.println(16 >> 2); // 4 (signed right shift = /2^2)
System.out.println(-1 >>> 28);// 15 (unsigned right shift)
Ternary Operator
int age = 20;
String status = (age >= 18) ? "Adult" : "Minor";
12. Equality: == vs .equals()
| Comparison | == | .equals() |
|---|---|---|
| Primitives | Compares values | N/A (primitives have no methods) |
| Objects | Compares references (identity) | Compares content (if overridden) |
String a = new String("hi");
String b = new String("hi");
System.out.println(a == b); // false (different objects)
System.out.println(a.equals(b)); // true (same content)
int x = 5, y = 5;
System.out.println(x == y); // true (value comparison)
Rule of thumb: use
==for primitives,.equals()for objects (Strings, wrappers, collections).
13. Java 21 Notes
| Feature | Relevance to this topic |
|---|---|
| Text Blocks (15+) | Multi-line String literals ("""). |
var (10+) | Local type inference for cleaner variable declarations. |
| String methods (11+) | strip(), isBlank(), repeat(), lines(). |
Pattern matching for instanceof (16+) | if (obj instanceof String s) { use s; } — no manual cast. |
Pattern matching for switch (21) | Type-based branching on values. |
Integer/Long etc. | Constructors removed; use valueOf/autoboxing. |
Pattern Matching for instanceof
Object obj = "Hello";
if (obj instanceof String s) {
System.out.println(s.length()); // 's' is auto-cast and scoped
}
14. Certification Traps
| # | Trap |
|---|---|
| 1 | Integer cache: == is true for -128..127, false outside. Use .equals(). |
| 2 | Unboxing a null wrapper → NullPointerException. |
| 3 | Autoboxing + widening together is not allowed (Long l = 5; fails). |
| 4 | byte b = b + 1; fails, but b += 1; works (compound assignment casts implicitly). |
| 5 | 'A' + 'B' = 131 (int), not "AB". |
| 6 | Casting narrows with truncation, not rounding; overflow wraps around. |
| 7 | 1 / 0 throws; 1.0 / 0 = Infinity; 0.0/0.0 = NaN. |
| 8 | String is immutable — s.concat(...) without reassignment does nothing. |
| 9 | StringBuilder has no equals() override — .equals() compares references. |
| 10 | var x = null; and var x; are compile errors. |
| 11 | & evaluates both sides (no short-circuit) → can cause NPE where && is safe. |
| 12 | Underscores in literals can't touch the start, end, decimal point, or radix prefix. |
| 13 | long l = 10000000000; fails without L suffix. |
| 14 | parseInt returns int; valueOf returns the wrapper object. |
| 15 | NaN == NaN is false; use Double.isNaN(x). |
15. Common Mistakes
| Mistake | Fix |
|---|---|
Comparing wrappers with == | Use .equals(). |
Forgetting L on large long literals | long x = 5_000_000_000L; |
Expecting 5/2 to be 2.5 | Use a double: 5.0/2. |
Modifying a String and ignoring result | Reassign: s = s.trim(); |
Using String concatenation in big loops | Use StringBuilder. |
Casting double to int and expecting rounding | It truncates; use Math.round(). |
| Unboxing without null check | Validate before unboxing. |
Using == on StringBuilder content | Compare .toString() values. |
16. Interview Questions
Q1. How many primitive types does Java have?
Eight: byte, short, int, long, float, double, char, boolean.
Q2. What is autoboxing and unboxing? Autoboxing converts a primitive to its wrapper automatically; unboxing converts a wrapper back to a primitive automatically.
Q3. Why does Integer a = 127; Integer b = 127; a == b return true but 128 returns false?
Because Java caches Integer objects from -128 to 127, so 127 reuses the same cached object while 128 creates new objects.
Q4. What happens when you unbox a null Integer?
A NullPointerException is thrown at runtime.
Q5. Difference between widening and narrowing? Widening (small→large) is automatic and lossless; narrowing (large→small) requires an explicit cast and may lose data.
Q6. Why is String immutable? For security, thread-safety, caching (string pool), and safe sharing. Any "change" produces a new String.
Q7. Difference between String, StringBuilder, and StringBuffer? String is immutable; StringBuilder is mutable and not thread-safe; StringBuffer is mutable and thread-safe (synchronized).
Q8. What is the String pool? A memory region where String literals are interned so identical literals share one object.
Q9. Difference between == and .equals()?
== compares references (or primitive values); .equals() compares content when overridden.
Q10. What does b += 5 do that b = b + 5 cannot for a byte?
Compound assignment performs an implicit narrowing cast, so it compiles; b = b + 5 produces an int that won't auto-fit into byte.
Q11. What is the result of 1.0 / 0?
Infinity (floating-point division by zero does not throw).
Q12. Can var be used for instance fields?
No — var is only for local variables with an initializer.
17. Quick Revision Notes
- 8 primitives; only fields get defaults, locals don't.
- Wrappers:
Integer,Double, ... ; cache range -128..127 for integral wrappers. - Use
.equals()for wrappers/Strings;==compares references for objects. - Unboxing
null→ NPE. - Boxing + widening together is not automatic.
var= local inference; needs initializer; no fields/params/return/null.- Widening is automatic; narrowing needs an explicit cast (truncates, wraps on overflow).
- Compound assignment (
+=) hides an implicit cast. byte/short/charpromote tointin arithmetic.Stringimmutable + pooled;new Stringmakes a heap object.StringBuildermutable, fast, noequals()override.1/0throws;1.0/0= Infinity;0.0/0.0= NaN;NaN == NaNis false.&&/||short-circuit;&/|always evaluate both sides.
18. One-Page Cheat Sheet
====================== DATA TYPES & OPERATORS CHEAT SHEET ======================
PRIMITIVES (8)
byte(8) short(16) int(32) long(64) float(32) double(64) char(16) boolean
defaults: 0 / 0.0 / '\u0000' / false (FIELDS ONLY; locals need init)
long needs L, float needs f: long x=5L; float y=3.14f;
WRAPPERS
byte->Byte int->Integer ... boolean->Boolean
valueOf -> wrapper object | parseInt -> primitive
CACHE -128..127 : Integer a=127,b=127 -> a==b true ; 128 -> false
ALWAYS compare with .equals()
AUTOBOX / UNBOX
Integer i = 5; int p = i;
null unbox -> NullPointerException
boxing + widening together = NOT allowed (Long l = 5; FAILS)
var (Java 10+)
local only, must initialize, no null, no fields/params/returns
var x = 10; // int var s = "hi"; // String
WIDENING (auto): byte->short->int->long->float->double ; char->int...
NARROWING (cast): int i = (int) 9.99; // 9 (truncate)
overflow wraps: (byte)128 -> -128
COMPOUND CAST: byte b=10; b+=5; // OK ; b=b+5; // ERROR
PROMOTION IN EXPR
byte/short/char -> int before arithmetic
'A' + 'B' = 131 (int) ; "" + 'A' + 'B' = "AB"
5/2=2 ; 5.0/2=2.5 ; 1/0 -> Exception ; 1.0/0 -> Infinity ; 0.0/0.0 -> NaN
STRING (immutable, pooled)
"x"=="x" true ; new String("x")=="x" false ; use .equals()
s.concat(...) must be reassigned ; strip/isBlank/repeat (Java 11+)
text block: """ ... """
STRINGBUILDER (mutable, not thread-safe)
append insert delete reverse replace ; NO equals() override
StringBuffer = synchronized version
OPERATORS
pre/post: i++ uses-then-incr ; ++i incr-then-uses
&& || short-circuit ; & | evaluate both
<< *2^n ; >> /2^n signed ; >>> unsigned
ternary: cond ? a : b ; instanceof String s (pattern, Java 16+)
EQUALITY
primitives -> == | objects -> .equals() | NaN==NaN -> false
================================================================================
End of 02 - Variables, Data Types, and Operators.