Variables & Basic Types

Course 1 · Ch 2
Variables & Basic Types
Where Java's types are guaranteed exact — and where == quietly stops meaning what it looks like it means

java1-1 showed every value living inside a class. This chapter shows the one deliberate exception — and the real trap it creates.

Primitive Types

Java has exactly eight primitives — byte, short, int, long, float, double, char, boolean — each with an exact, guaranteed size across every platform, per the JVM specification itself. This is genuinely Rust-like, not C-like: c1-2's own material established that C only guarantees a minimum size for int. Java's primitives agree with Rust here, not with C.

Reference Types

Everything else — objects, arrays, String — is a reference type, stored as a reference to heap-allocated data, not the raw value itself. Conceptually similar to C's own pointer/value distinction (c1-7), but Java references cannot be manipulated with pointer arithmetic at all — no c1-7-style arithmetic; dereferencing is always implicit.

Primitives vs. Objects — Why Both Exist

A real, practical reason: primitives are stored directly — on the stack, or inline within an object — avoiding the overhead a full object/reference would carry for something as simple as an int. A deliberate performance-vs-uniformity tradeoff; making everything a full object, as some "purer" OOP languages do, has real, measurable overhead.

Boxing & Unboxing

Integer is the object wrapper class for the primitive int. Autoboxing (a primitive silently becoming a wrapper object) and auto-unboxing (the reverse) happen automatically in many contexts since Java 5.

List<Integer> nums = new ArrayList<>(); nums.add(5); // int 5 is autoboxed into an Integer — the collection can only hold objects

A Real Boxing Gotcha — Integer Caching

Integer a = 127; Integer b = 127; a == b; // true — both reference the SAME cached object Integer c = 200; Integer d = 200; c == d; // false — two genuinely separate objects, outside the cache range

A genuinely surprising, real, documented JVM behavior: Java caches small boxed Integer values, -128 to 127. Trips up even experienced Java programmers, since small test values often happen to fall inside the cached range and hide the bug.

== vs. .equals()

The general rule this gotcha is an instance of: == compares references for objects (are these the same object in memory) but compares values for primitives (since there's no reference to compare at all). .equals() is the method for genuine value comparison between objects.

ConceptC (c1-2)RustJava
Integer type sizeminimum only, platform-dependentexact, guaranteedexact, guaranteed
Value vs. reference defaulteverything is a value; pointers are explicitexplicit ownership/borrowingprimitives are values; everything else is a reference
Object equality operatorn/a — no objects== is value equality (PartialEq)== is reference identity for objects, not value equality
Use .equals() for object value comparison, always
Reserve == for reference identity checks (or genuine primitive comparisons) — .equals() is the everyday habit for comparing what two objects actually contain.
Integer caching only "works" for small test values
== on boxed Integer values outside -128..127 will not reliably behave the way small test values might suggest — a genuine, real source of confusing bugs that only manifest once real data exceeds the cached range.

Coding Challenges

Challenge 1

Declare two Integer variables both set to 100, compare them with ==, then declare two more both set to 500 and compare those with ==. Print both results and explain the difference.

📄 View solution
Challenge 2

Repeat Challenge 1's 500-value comparison, but use .equals() instead of ==. Report the result and explain why it now behaves correctly regardless of the cache range.

📄 View solution
Challenge 3

Explain why Java's primitive types are described as "Rust-like" rather than "C-like" in terms of size guarantees, tying your answer directly back to c1-2's own material on C's int.

📄 View solution

Chapter 2 Quick Reference

  • Eight primitives — exact, guaranteed sizes, unlike C's own minimum-only guarantee
  • Everything else is a reference type — no pointer arithmetic, unlike C's pointers
  • Autoboxing/auto-unboxing convert transparently between a primitive and its wrapper class (e.g. int/Integer)
  • Integer caching (-128..127) means small boxed values happen to share references — a real, documented gotcha
  • == is reference identity for objects; .equals() is genuine value comparison — use .equals() by default
  • Next chapter: operators, control flow, switch expressions, and pattern matching