Topic 4.4
The this Keyword
In one line
this is a reference to the object the current method or constructor is running on. You use it to tell a field from a parameter with the same name, to pass or return the current object, and (as this(...)) to call another constructor.
Think of it like this
In a classroom, every pupil says "my bag". The words are the same, but each "my" means a different person, depending on who is speaking. In Java, this is the method's "my": inside rex.bark() it means Rex, and inside bella.bark() the very same code means Bella.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- `this`
- A reference to the current object: the one the method was called on, or the one being constructed.
- Shadowing
- When a local variable or parameter has the same name as a field, the closer name wins and hides the field inside that block.
- Disambiguate
- Make clear which of two things with the same name you mean.
this.xmeans the field,xmeans the parameter. - Fluent interface
- A style where methods return
this, so you can write several calls in one chain:a.b().c().d(). - Method chaining
- Calling a method on the result of the previous call, in one expression.
- Self-assignment
- Assigning a variable to itself, like
x = x;. It does nothing, and it's usually a bug.
Step by step
01The same code, a different "me" each time
void describe() { System.out.println(this.name); } runs on whatever object you call it on. rex.describe() sets this to Rex; bella.describe() sets this to Bella.
Writing name alone is the same as this.name when nothing else is called name. The compiler adds the this. for you. You only *need* to write it when there's a conflict.
class Dog {
String name;
void describe() {
System.out.println("I am " + this.name); // same as: name
}
}02Shadowing: when a parameter hides a field
Good parameter names often match field names: a constructor that sets name naturally takes a parameter called name. Inside that constructor, the parameter is the nearest declaration, so name means the parameter.
name = name; assigns the parameter to itself. It compiles, does nothing, and the field keeps its default null. Many IDEs and linters flag it, but javac doesn't.
this.name = name; says: the field of this object gets the parameter's value. This is the standard Java idiom.
03Passing this: an object hands itself over
Sometimes an object needs to give a reference to itself to someone else: a student enrolling in a course, a button registering with a window. Inside Student.enrol(Course c), c.add(this) passes the current student.
Be careful doing this inside a constructor: the object isn't finished yet, and whoever receives this might use it too early (see Pro notes).
class Student {
String name;
void enrol(Course c) {
c.add(this); // give the course a reference to me
}
}04Returning this: fluent chaining
If a method ends with return this; and declares the class as its return type, the caller gets the same object back and can call another method on it straight away.
new Order().add("tea").add("samosa").discount(10) is three calls on one Order object. StringBuilder.append works exactly like this (Topic 6.3).
Order add(String item) {
items += item + " ";
return this; // hand back the same object
}05No this in static code
static methods belong to the class, not to an object (Topic 4.6). When main runs, no Main object exists, so there's nothing for this to refer to.
That's also why a static method can't use instance fields without naming an object: count really means this.count, and this doesn't exist there.
06What this is in the bytecode
For an instance method, the JVM puts the receiver into local variable slot 0 before the method runs. this compiles to aload_0. Parameters start at slot 1.
That's also why this can never be null: calling a method on a null reference throws NullPointerException *before* the method starts, so a running instance method always has a real object in slot 0.
Try it yourself
- 1
Find the silent bug
In "Shadowing bug vs the fix", rename BuggyDog's parameters to
nanda(and the body toname = n; age = a;). Predict the output, then run. Nowthis.is unnecessary. Why? - 2
Break the chain
In the fluent
Orderexample, changediscountto returnvoid. Read the compiler error you get on the chain, and explain which call broke it. - 3
Count the enrolments
Add a field
int coursestoStudentand increment it inenrolusingthis.courses++. Enrol Asha in two courses and print her count.
Code & diagrams
Expected output
buggy: null, 0
good: Rex, 3Expected output
tea samosa samosa = 45
same object? true
tea samosa samosa water = 55Expected output
Core Java: Asha Ben
first enrolled is asha? trueBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Forget this. in a constructor
In a constructor Dog(String name), write name = name; instead of this.name = name;.
Break #2
Use this inside main
Add a field int count; to Main and write System.out.println(this.count); inside main.
Myth vs fact
Myth
You must always write this. before fields.
Fact
Only when a local variable or parameter with the same name shadows the field. Otherwise the compiler adds this. for you. Some teams write it always for clarity; that's style, not a rule.
Myth
this can be null.
Fact
Never. A call on a null reference throws before the method starts, so a running instance method always has a real object as this.
Myth
this() and this. are the same feature.
Fact
this.x reads a member of the current object. this(...) calls another constructor and is allowed only as the first statement of a constructor.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
In bytecode
thisis local slot 0 (aload_0) in every instance method and constructor; parameters start at slot 1. Static methods have no slot reserved for it, which is the low-level reasonthisis illegal there. - ▸
**Escaping
this** from a constructor (starting a thread with it, publishing it to a static list, registering a listener) lets other code see a partly initialised object. The JLS 17.5 guarantee that other threads see correctly initialisedfinalfields only holds ifthisdoesn't escape before the constructor finishes. Use a static factory that constructs first and registers afterwards. - ▸
In a lambda,
thisrefers to the enclosing instance; in an anonymous class it refers to the anonymous object. This is one of the real semantic differences between the two (Phase 11), and why lambdas capturethiswhen they use instance members (which can keep the outer object alive). - ▸
Fluent setters that
return thisdon't work well with inheritance: a parent'sname()returns the parent type, so a child's methods disappear from the chain. Builders solve it with a self-type generic (B extends Builder<B>) or by keeping builders final.
Remember this
- 1
thisis a reference to the current object: the receiver the method was called on, or the object being built in a constructor. It's not a variable you declare; the compiler provides it in every instance method and constructor, as local slot 0 in the bytecode. - 2
The most common use is disambiguation. In
Point(int x, int y) { this.x = x; }, the parameterxshadows (hides) the fieldx, so plainxmeans the parameter.this.xsays "the field of this object". Forgetthis.and you writex = x;, assigning the parameter to itself: the field silently stays 0. - 3
You can pass
thisto another method (registry.add(this)) when an object needs to hand itself over, and you can returnthisfrom a method so calls can be chained:builder.name("Asha").age(30).city("Pune"). This is called a fluent interface. - 4
this(...)(with parentheses) is a different thing: a call to another constructor of the same class, allowed only as the first statement of a constructor (Topic 4.3). - 5
staticmethods have nothis, because they don't run on any object. Usingthisinmainis a compile error:non-static variable this cannot be referenced from a static context. - 6
thisisfinal: you can't assign to it (this = other;doesn't compile). Inside an inner class, plainthismeans the inner object andOuter.thismeans the enclosing one (Topic 5.13). Inside a lambda,thismeans the enclosing object, not the lambda (Phase 11).
Explain it without notes
What does this refer to inside an instance method, and inside a constructor?
Why does name = name; in a constructor compile but not work?
Give two reasons to pass or return this, with an example of each.
Why can't static methods use this?
Practice
Write a class Person with fields name and age, a constructor that uses parameters with the same names, and a method isOlderThan(Person other) that uses this.age and other.age. Show it with two people.
Write a fluent class Text with methods add(String s), space() and upper() that each return this, and a toString() returning the built text. Build HELLO WORLD with one chain.
Write a class Node with int value and Node next, and a method Node link(Node n) that sets this.next = n and returns n. Build the list 1 -> 2 -> 3 in one chain and print it.
Trade-offs
- ↔
Writing
this.everywhere makes field access obvious when reading, but adds noise. Most style guides use it only where needed (constructors and setters with matching parameter names). - ↔
Fluent
return thisAPIs read beautifully for builders and configuration, but they hide that the same object is being mutated, which surprises callers who expected a new object (compare immutableString, whose methods return new strings, Topic 4.11).
Done when you can
Done when you can explain what
thisrefers to in a method and in a constructor.Done when you can spot and fix the
x = x;shadowing bug.Done when you can write a fluent API with
return this.Done when you can explain why
thisdoesn't exist in static methods.Done when you know
this(...)calls a constructor andthis.xreads a member.