Java • Syntax and Core Types

Assignment vs. Equality — Distinguish assignment (=) from equality (==) and object equality (.equals)

Master the three most confused operators in Java and write bug-free comparisons every time.

Java programming emblem with a coffee cup, code braces, and terminal
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

If you have ever written if (x = 5) when you meant if (x == 5), you are in good company. The confusion between assignment and equality testing is one of the most common bugs in programming history. The story of how we ended up with two similar-looking symbols that do completely different things stretches back to the earliest days of computer science.

1957 • FORTRAN Uses = for Assignment

IBM's FORTRAN language adopted the = symbol for assignment, borrowing it from mathematics. This single decision influenced nearly every language that followed, even though it conflicted with math's meaning of equality.

1972 • C Introduces == for Equality

Dennis Ritchie's C language kept = for assignment but introduced == for equality comparison. This solved the ambiguity problem but created a new source of typos that haunts programmers to this day.

1995 • Java Inherits C's Operators

James Gosling designed Java to look familiar to C and C++ programmers. Java kept = and == but added stronger type-checking to catch accidental assignment inside conditions.

1995 • Java Adds .equals() for Objects

Because Java uses references for objects, == only checks whether two variables point to the same memory location. The .equals() method was introduced so programmers could compare the actual content of objects.

Understanding these three operations — = for assignment, == for primitive equality, and .equals() for object equality — is essential for writing correct Java code. The question at the heart of this lesson is: how does Java decide what it means when you use each of these symbols?

SECTION 2

Core Principles & Definitions

Before diving into examples, you need a firm grip on what each operator actually does behind the scenes. In Java, every variable either holds a primitive value (like an int or boolean) directly, or it holds a reference — an address that points to an object stored somewhere in memory. This distinction is the key to understanding everything in this lesson.

1

Assignment (=)

The single equals sign stores a value into a variable. Writing x = 10 puts the number 10 into the box labeled x. It does NOT ask a question — it gives a command.
2

Equality (==)

The double equals sign asks a yes-or-no question: do these two values match? For primitives, it compares the actual numbers or characters. For objects, it only checks whether both variables point to the exact same object in memory.
3

Object Equality (.equals())

The .equals() method asks: do these two objects have the same content? Two separate String objects that both hold "hello" are .equals() to each other, even though == might say they are different.
4

Primitives vs. References

Primitives (int, double, boolean, etc.) store values directly, so == works perfectly. Reference types (String, arrays, objects) store memory addresses, so you almost always need .equals().
✦

KEY TAKEAWAY

Think of it like houses. Assignment (=) is like moving into a house — you place yourself inside. == on objects is like asking "Do you live at the exact same address?" — two identical houses on different streets would fail. .equals() is like asking "Do your houses have the same floor plan and furniture?" — two different houses with identical interiors would pass.

SECTION 3

Visual Explanation — Memory Model

The diagram below shows what happens in Java's memory when you create variables and compare them. The left side shows primitive variables that hold their values directly. The right side shows reference variables that hold memory addresses pointing to objects on the heap.

PRIMITIVE VARIABLESREFERENCE VARIABLESint a5int b5a == b → true ✓(same value: 5 equals 5)int c5int d10c == d → false ✗(different value: 5 ≠ 10)String s1@0x100String s2@0x200"hello""hello"s1 == s2 → false ✗(different addresses: 0x100 ≠ 0x200)s1.equals(s2) → true ✓(same content: "hello" matches "hello")String s3@0x100String s4@0x100s3 == s4 → true ✓(same address: both point to @0x100)s3.equals(s4) → true ✓Assignment Example:a = 10;Now a holds 10 (old value 5 is gone)
Left: primitive variables store values directly, so == compares the values themselves. Right: reference variables store memory addresses; == compares addresses while .equals() compares the content the addresses point to.

Notice in the diagram that s1 and s2 both contain the text "hello", but they live at different memory addresses (0x100 and 0x200). This is why == returns false — it only sees the different addresses. Meanwhile, .equals() looks past the addresses and examines the actual characters, finding them identical. In contrast, s3 and s4 share the same address, so both == and .equals() return true.

SECTION 4

How Each Operator Works Under the Hood

The Assignment Operator (=)

When Java encounters x = 10, it performs a single action: it takes the value on the right side and copies it into the variable on the left side. The right side is evaluated first, so you can write x = x + 1 — Java computes x + 1 using the old value, then stores the result back into x. For reference types, assignment copies the address, not the object itself. After s2 = s1, both variables point to the exact same object.

The == Operator

The == operator returns a boolean value — either true or false. For primitive types (int, double, char, boolean, etc.), it compares the actual values directly. For reference types (any object, including String), it compares the memory addresses. Two objects can have identical data inside them, but if they are stored at different addresses, == will return false.

The .equals() Method

Every Java object inherits a .equals() method from the Object class. By default, .equals() behaves exactly like == — it compares addresses. However, many classes (like String, Integer, and ArrayList) override this method to compare the actual content instead. When you call "hello".equals("hello"), Java's String class checks each character one by one to determine equality.

⚠

Watch Out: The String Pool

Java has a special optimization called the String pool. When you write a String literal like String s = "hello", Java reuses the same object for identical literals, so == might return true. But new String("hello") always creates a fresh object. Never rely on == for Strings — always use .equals().

SECTION 5

Side-by-Side Comparison & Classification

The table below summarizes when to use each operator. Study it carefully — this is the single most useful reference for avoiding common bugs.

Feature= (Assignment)== (Equality).equals() (Object Equality)
PurposeStore a value in a variableCompare two values or addressesCompare the content of two objects
ReturnsThe assigned value (side effect)true or falsetrue or false
Use with primitivesYes — stores the valueYes — compares values directlyNo — primitives don't have methods
Use with objectsYes — copies the reference (address)Checks if both point to same objectChecks if objects have same content
Common mistakeUsing = inside an if-conditionUsing == to compare String contentCalling on null (NullPointerException)
Exampleint x = 5;x == 5 → trues1.equals(s2)

Comparison of = , == , and .equals()

DECISION FLOWCHART: Which Operator Should I Use?What do I want to do?Store a valueCompare valuesUse =What type?PrimitiveObjectUse ==Same object or content?Same contentSame objectUse .equals()Use ==Tip: When in doubt with objects, .equals() is almost always the safer choice.
Follow this decision tree whenever you are unsure which operator to use. Start at the top and follow the branches based on whether you want to store a value or compare values, and whether you are working with primitives or objects.

SECTION 6

Worked Example — Tracing Code Step by Step

Let's trace through a short Java program and predict exactly what each line prints. This exercise builds the mental muscle you need to debug comparison bugs in your own code.

Tracing Assignment and Equality

  1. 1

    Step 1 — Read the Code

    Consider the following program: int x = 5; int y = 5; String a = new String("cat"); String b = new String("cat"); String c = a; We need to evaluate: x == y, a == b, a.equals(b), and a == c.
  2. 2

    Step 2 — Evaluate x == y

    Both x and y are primitives (int). The == operator compares their actual values: 5 and 5. Since they match, the result is true.
    x == y → true
  3. 3

    Step 3 — Evaluate a == b

    Both a and b are references to String objects. Because we used new String("cat") for each, Java created two separate objects at two different memory addresses. The == operator compares the addresses, which are different.
    a == b → false
  4. 4

    Step 4 — Evaluate a.equals(b)

    Now we use .equals(), which the String class has overridden to compare character-by-character. Both objects contain 'c', 'a', 't' — every character matches.
    a.equals(b) → true
  5. 5

    Step 5 — Evaluate a == c

    Look at line 5: String c = a; — this is assignment. It copies the address stored in a into c. Now both variables point to the exact same object in memory. When == compares their addresses, they match.
    a == c → true

SECTION 7

Common Pitfalls & How to Avoid Them

Even experienced programmers sometimes mix up these operators. The table below lists the most common mistakes, what actually happens when you make them, and the fix.

MistakeWhat HappensCorrect Version
if (x = 5)Assigns 5 to x instead of comparing. In Java, this causes a compile error if x is an int (since int is not boolean).if (x == 5)
if (str1 == str2)Compares memory addresses instead of text content. May give unexpected false results even when strings have the same text.if (str1.equals(str2))
if (str1.equals(null))Always returns false, which is fine. But calling null.equals(str1) throws a NullPointerException.Put the known non-null value first: "hello".equals(str1)
Comparing wrapper objects with ==Integer a = 200; Integer b = 200; — a == b is false because cached range is only −128 to 127.a.equals(b)

Common operator mistakes and their fixes

🔑

GOLDEN RULE

When comparing objects in Java, use .equals() by default. The only time you intentionally use == on objects is when you specifically need to know whether two variables point to the exact same object in memory (which is rare). For primitives, == is always the right choice.

SECTION 8

Connection to Advanced Topics

As you advance in Java, the ideas from this lesson connect to several deeper topics. Understanding the difference between identity (same address) and equality (same content) is a concept that shows up in data structures, testing, and software design.

This LessonAdvanced Topic
.equals() compares contentWhen you write your own classes, you can override .equals() to define what "equal" means for your objects.
== compares addressesData structures like HashMap and HashSet rely on both .equals() and .hashCode() working together correctly.
String pool reuses objectsImmutability — Strings are safe to share because they can never change. This design pattern appears throughout advanced Java.
Assignment copies referencesDeep vs. shallow copy — Understanding that = on objects copies only the reference leads to learning about cloning and defensive copying.

How this lesson's concepts connect to advanced Java topics

You do not need to master all of these advanced topics right now. The important thing is to build a solid foundation with =, ==, and .equals(). Once these become second nature, you will find that the advanced topics feel like natural extensions rather than confusing new material.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain in your own words why == is safe to use for comparing int values but not for comparing String objects. What is the fundamental difference between how Java stores these two types?
Show answer
An int is a primitive type, which means the variable directly holds the numeric value. When you write ==, Java compares those actual numbers. A String is a reference type, so the variable holds a memory address pointing to the object. Using == on Strings compares the addresses, not the text content. Two different String objects can contain identical text but live at different addresses, causing == to return false unexpectedly.

Question 2: BASIC

What does the following code print? int a = 7; int b = 7; System.out.println(a == b); a = 10; System.out.println(a == b);
Show answer
The first println prints true because both a and b hold the value 7, and == compares primitive values directly. After the assignment a = 10, the variable a now holds 10 while b still holds 7. The second println prints false because 10 ≠ 7. Notice that changing a did not affect b — primitives are independent copies.

Question 3: INTERMEDIATE

Predict the output of each line: String s1 = "apple"; String s2 = "apple"; String s3 = new String("apple"); System.out.println(s1 == s2); // Line A System.out.println(s1 == s3); // Line B System.out.println(s1.equals(s3)); // Line C
Show answer
Line A prints true. Both s1 and s2 are String literals, so Java's String pool makes them point to the same object — their addresses match. Line B prints false. The new keyword forces Java to create a brand-new String object at a different address, so == fails. Line C prints true. The .equals() method compares the actual characters, and both strings contain 'a', 'p', 'p', 'l', 'e', so they are equal.

Question 4: APPLIED

You are writing a login system. A user types their password, and you need to compare it to the stored password. Which of the following is correct and why? Option A: if (inputPassword == storedPassword) Option B: if (inputPassword.equals(storedPassword)) Option C: if (storedPassword.equals(inputPassword)) Which option is the best practice, and what could go wrong with the others?
Show answer
Option A is wrong because passwords are Strings, and == would compare memory addresses, not the actual password text. User input typically creates new String objects, so this would almost always return false. Option B is better — it compares the text content correctly. However, if inputPassword is null (the user somehow submitted nothing), calling .equals() on null would crash with a NullPointerException. Option C is the best practice. Since storedPassword is stored by your system and should never be null, calling .equals() on it is safe — if inputPassword is null, it simply returns false without crashing.

Question 5: CRITICAL THINKING

Consider this code: Integer x = 100; Integer y = 100; Integer a = 200; Integer b = 200; System.out.println(x == y); // Line 1 System.out.println(a == b); // Line 2 Line 1 prints true but Line 2 prints false. Both use == on Integer objects. Research or reason about why the results differ, and explain what lesson this teaches about relying on == with wrapper types.
Show answer
Java caches Integer objects for values between −128 and 127. When you write Integer x = 100, Java uses autoboxing and pulls the Integer from the cache. Since y is also 100, it gets the same cached object, so == returns true (same address). However, 200 is outside the cache range. Java creates two separate Integer objects for a and b, so they have different addresses and == returns false. The lesson is clear: never rely on == for any object types, including wrapper classes like Integer. Always use .equals() to compare values.

SUMMARY

Lesson Summary

Summary

Java uses three distinct mechanisms for working with values: assignment (=) stores a value or reference into a variable, the == operator compares primitive values directly or compares the memory addresses of reference types, and the .equals() method compares the actual content of objects. For primitive types like int, double, and boolean, use == for comparisons. For objects like String, always use .equals().

Remember the key distinctions: = gives a command ("put this value here"), while == asks a question ("are these the same?"). The String pool can make == appear to work on Strings in some cases, but this is unreliable. Watch out for NullPointerException when calling .equals() on a variable that might be null — call the method on the value you know is not null. These habits will prevent countless debugging headaches as your programs grow more complex.

Varsity Tutors • Java • Assignment vs. Equality