MindIQ Academy

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

  1. Primitive Types
  2. Literals & Number Formats
  3. Wrapper Classes
  4. Autoboxing & Unboxing
  5. The var Keyword
  6. Type Promotion (Widening)
  7. Type Casting (Narrowing)
  8. Numeric Promotion in Expressions
  9. Strings
  10. StringBuilder
  11. Java Operators
  12. Equality: == vs .equals()
  13. Java 21 Notes
  14. Certification Traps
  15. Common Mistakes
  16. Interview Questions
  17. Quick Revision Notes
  18. 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.

TypeCategorySizeRangeDefaultExample
byteInteger8-bit-128 to 1270byte b = 100;
shortInteger16-bit-32,768 to 32,7670short s = 1000;
intInteger32-bit~ -2.1B to 2.1B0int i = 42;
longInteger64-bit~ -9.2E18 to 9.2E180Llong l = 99L;
floatFloating32-bit~6-7 decimal digits0.0ffloat f = 3.14f;
doubleFloating64-bit~15 decimal digits0.0double d = 3.14;
charCharacter16-bit0 to 65,535 (Unicode)'\u0000'char c = 'A';
booleanLogicalJVM-dependenttrue / falsefalseboolean ok = true;

Key Points

  • Defaults apply only to fields (instance/static). Local variables have no default and must be initialized.
  • char is unsigned (0–65535); the other integral types are signed.
  • boolean cannot be cast to/from any numeric type. boolean b = (boolean) 1; is illegal.
  • byte and short are auto-promoted to int in 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

LiteralExampleNotes
Decimalint x = 100;Base 10.
Binary (Java 7+)int b = 0b1010;Prefix 0b. = 10
Octalint o = 010;Prefix 0. = 8
Hexadecimalint h = 0xFF;Prefix 0x. = 255
Underscores (Java 7+)int m = 1_000_000;Readability only.
long suffixlong l = 100L;L (or l).
float suffixfloat f = 3.14f;f (or F) required.
double suffixdouble d = 3.14d;d optional (default).
charchar 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.

PrimitiveWrapper
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

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

parseXxx returns a primitive; valueOf returns 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

RuleExampleValid?
Local variables onlyvar x = 5; inside method
Must have initializervar x;
Cannot be null alonevar x = null;
Not for fieldsclass C { var x = 5; }
Not for method paramsvoid m(var x)
Not for return typesvar m() {...}
OK in for loopsfor (var i = 0; ...)
Enhanced forfor (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

var is a reserved type name, not a keyword — so you could name a method or variable var, 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)
FromWidens automatically to
byteshort, int, long, float, double
shortint, long, float, double
charint, long, float, double
intlong, float, double
longfloat, double
floatdouble

Note: long -> float and int -> float are 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:

  1. byte, short, char are promoted to int before any arithmetic.
  2. If either operand is long, the result is long.
  3. If either is float, the result is float.
  4. If either is double, the result is double.
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

FeatureStringStringBuilderStringBuffer
Mutable?❌ No✅ Yes✅ Yes
Thread-safe?✅ (immutable)❌ No✅ Yes (synchronized)
PerformanceSlow for many editsFastSlower than Builder
Use whenFixed textSingle-thread buildingMulti-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

StringBuilder does NOT override equals() — comparing two builders with .equals() compares references, not contents.


11. Java Operators

Operator Categories

CategoryOperators
Arithmetic+ - * / %
Unary+ - ++ -- ! ~
Relational< > <= >= == !=
Logical (short-circuit)&& ||
Bitwise / non-short-circuit& | ^ ~
Shift<< >> >>>
Assignment= += -= *= /= %= ...
Ternary? :
Type comparisoninstanceof

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
OperatorEvaluates 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()
PrimitivesCompares valuesN/A (primitives have no methods)
ObjectsCompares 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

FeatureRelevance 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
1Integer cache: == is true for -128..127, false outside. Use .equals().
2Unboxing a null wrapper → NullPointerException.
3Autoboxing + widening together is not allowed (Long l = 5; fails).
4byte b = b + 1; fails, but b += 1; works (compound assignment casts implicitly).
5'A' + 'B' = 131 (int), not "AB".
6Casting narrows with truncation, not rounding; overflow wraps around.
71 / 0 throws; 1.0 / 0 = Infinity; 0.0/0.0 = NaN.
8String is immutable — s.concat(...) without reassignment does nothing.
9StringBuilder has no equals() override — .equals() compares references.
10var x = null; and var x; are compile errors.
11& evaluates both sides (no short-circuit) → can cause NPE where && is safe.
12Underscores in literals can't touch the start, end, decimal point, or radix prefix.
13long l = 10000000000; fails without L suffix.
14parseInt returns int; valueOf returns the wrapper object.
15NaN == NaN is false; use Double.isNaN(x).

15. Common Mistakes

MistakeFix
Comparing wrappers with ==Use .equals().
Forgetting L on large long literalslong x = 5_000_000_000L;
Expecting 5/2 to be 2.5Use a double: 5.0/2.
Modifying a String and ignoring resultReassign: s = s.trim();
Using String concatenation in big loopsUse StringBuilder.
Casting double to int and expecting roundingIt truncates; use Math.round().
Unboxing without null checkValidate before unboxing.
Using == on StringBuilder contentCompare .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 nullNPE.
  • 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/char promote to int in arithmetic.
  • String immutable + pooled; new String makes a heap object.
  • StringBuilder mutable, fast, no equals() override.
  • 1/0 throws; 1.0/0 = Infinity; 0.0/0.0 = NaN; NaN == NaN is 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.