Object-Oriented Programming · Lesson 49 of 150
this Keyword
See how the Java this keyword works in a pizza order app: fields vs parameters, this() calls, passing this, chaining and why static code can't use it.
Call a pizza shop and say, "Add extra cheese to my order." The person at the counter knows which order you mean, because you are the one talking. You did not read out an order number. The word "my" was enough to point at your order among the dozens on the board.
Inside a Java object, the keyword this plays the role of "my". When a method runs, this points to the object that the method was called on. It sounds small, yet it solves several everyday problems: name clashes, repeated constructor code, method chaining and handing an object to a helper. By the end of this page you will know all six common uses and why this disappears inside static code.
What is the this Keyword?
You never declare this. Java supplies it automatically. Its type is the class you are in, and it can never be null, because a method cannot run on an object that does not exist.
The six common uses are:
this.fieldto reach a field hidden by a parameter with the same name.this(...)to call another constructor of the same class.this.method()to call another method on the same object.- Passing
thisas an argument to a method. - Passing
thisto the constructor of another class. return this;so calls can be chained on one line.
Why is the this Keyword used?
Most of the time Java can guess which object you mean, so this stays invisible. It becomes necessary in a few clear situations.
- Clear names. Constructors read best when the parameter is called
size, just like the field.this.size = sizetells Java which one is which. - No repeated setup. Several constructors can share one "main" constructor through
this(...), so the setup code lives in one place. - Self-introduction. An object can hand itself to another object, for example an order registering itself with the kitchen.
- Fluent code. Setters that return
thislet you writeorder.size("L").crust("thin")instead of three separate lines. - Readability. Some teams write
this.before every field so fields and local variables are easy to tell apart.
Real-Life Example
Picture the order board in a pizza kitchen. Each slip is a separate order, and the chef works on one slip at a time. When the chef says "this slip needs olives", everyone knows which slip is meant: the one in the chef's hand.
Nobody writes the slip number on every instruction, because the slip in hand is obvious from context. A Java method is the chef, and each object is a slip. The same method code is shared by every object of the class, just as one chef handles every slip. The word this is the slip currently in hand. When the chef moves to the next slip, "this" means the new slip, although the chef's routine has not changed at all.
Syntax
javaclass ClassName { private String field; ClassName() { this("default"); } ClassName(String field) { this.field = field; } ClassName change(String value) { this.field = value; return this; } void share(Helper h) { h.accept(this); } }
Line by line:
this("default");calls the other constructor. It must be the very first statement in the constructor.this.field = field;copies the parameter (right side) into the field (left side).return this;sends back the same object, so another call can follow with a dot.h.accept(this);passes the current object to a helper that expects aClassName.
How the this Keyword Works
Each instance method receives a hidden extra parameter. You never see it in your code, but the compiler adds it. When you call orderA.addTopping("olive"), the JVM quietly passes orderA as that hidden parameter, and inside the method it is named this.
textorderA.addTopping("olive") | v JVM passes the hidden value this = orderA item = "olive" | v this.toppings.add(item) | v orderA's own list changes
Because only one copy of the method code exists, the hidden reference is how the code knows whose fields to touch. Call the same method on orderB, and this now holds orderB. Static methods do not receive this hidden reference, since they are called on the class, not on an object. That is exactly why this cannot appear in a static method.
Here is a detail that surprises many learners: you use this far more often than you type it. When a method writes toppings.add(item) or calls print() with no object in front, the compiler reads it as this.toppings.add(item) or this.print(). The keyword is silently added for you. Typing it yourself changes nothing in the compiled code. You only must write it when a parameter or local variable shares the field's name, because the nearest name always wins, and the local one is nearer.
Example Programs
Field vs Parameter and this() Chaining
javaclass PizzaOrder { private final String size; private final String flavour; private final int quantity; PizzaOrder(String flavour) { this("Medium", flavour, 1); System.out.println("Quick order used"); } PizzaOrder(String size, String flavour, int quantity) { this.size = size; this.flavour = flavour; this.quantity = quantity; System.out.println("Main constructor ran"); } void show() { System.out.println(quantity + " x " + size + " " + flavour); } } public class PizzaCounter { public static void main(String[] args) { PizzaOrder a = new PizzaOrder("Large", "Paneer", 2); a.show(); PizzaOrder b = new PizzaOrder("Farmhouse"); b.show(); } }
Output:
textMain constructor ran 2 x Large Paneer Main constructor ran Quick order used 1 x Medium Farmhouse
The one-argument constructor hands its work to the full constructor through this(...), so the field setup exists in one place. Inside that constructor, this.size is the field and plain size is the parameter.
Method Chaining with return this
javaimport java.util.ArrayList; import java.util.List; class CustomPizza { private String crust = "regular"; private final List<String> toppings = new ArrayList<>(); CustomPizza crust(String crust) { this.crust = crust; return this; } CustomPizza add(String topping) { this.toppings.add(topping); return this; } void print() { System.out.println(crust + " crust"); System.out.println("Toppings: " + toppings); } } public class ChainedOrder { public static void main(String[] args) { new CustomPizza() .crust("thin") .add("olive") .add("corn") .print(); } }
Output:
textthin crust Toppings: [olive, corn]
Every setter returns the same object, so each dot continues working on it. This is the style used by StringBuilder and many builder classes.
Passing the Current Object
javaclass Kitchen { void accept(TableOrder order) { System.out.println("Kitchen got table " + order.getTable()); } } class Bill { private final TableOrder order; Bill(TableOrder order) { this.order = order; } int total() { return order.getPizzas() * 250; } } class TableOrder { private final int table; private final int pizzas; TableOrder(int table, int pizzas) { this.table = table; this.pizzas = pizzas; } int getTable() { return table; } int getPizzas() { return pizzas; } void send(Kitchen k) { k.accept(this); } Bill makeBill() { return new Bill(this); } boolean isSame(TableOrder other) { return this == other; } } public class TableService { public static void main(String[] args) { TableOrder t7 = new TableOrder(7, 3); t7.send(new Kitchen()); System.out.println("Bill: Rs " + t7.makeBill().total()); System.out.println("Same object? " + t7.isSame(t7)); } }
Output:
textKitchen got table 7 Bill: Rs 750 Same object? true
The order passes itself to a method (k.accept(this)) and to a constructor (new Bill(this)). The last line proves that this inside the method is the very same object as t7 in main.
Common Mistakes
- Placing `this(...)` after other code. The call must be the first statement, or the compiler reports an error.
- Using `this` in a static method. Code such as
this.show()insidemainfails with "non-static variable this cannot be referenced from a static context". - Creating a constructor loop. If two constructors call each other through
this(...), the compiler rejects it as recursive invocation. - Letting `this` escape too early. Passing
thisto another object inside the constructor shares an object that is not fully built yet.
Interview Questions
What does `this` refer to in Java?
Ans:It refers to the current object, the one whose instance method or constructor is running. Java passes it in automatically, and it is never null.
Why can't `this` be used inside a static method?
Ans:A static method belongs to the class and runs without any object. There is no current object to point to, so the compiler does not allow this there.
Can we call both `this()` and `super()` in the same constructor?
Ans:No. Each must be the first statement, and only one statement can be first. A constructor that calls this(...) reaches the parent constructor through the constructor it calls.
What is method chaining and how does `this` help?
Ans:Method chaining means calling several methods one after another on the same object in a single statement. Each method returns this, so the next call works on the same object.
Is it necessary to write `this.` before every field?
Ans:No. It is only required when a local variable or parameter has the same name as the field. Many teams still use it for clarity, but the compiled result is identical.
Summary
thisis a reference to the current object inside constructors and instance methods.this.fieldseparates a field from a parameter of the same name.this(...)calls another constructor and must come first.- An object can pass
thisto methods and to other constructors. - Returning
thisenables method chaining. - Static methods have no current object, so they cannot use
this.
Related Topics
- Constructors: where
this(...)chaining happens. - super Keyword: the parent-class partner of
this. - static Keyword: why static code has no
this. - StringBuilder: a real class that uses method chaining.
Practice Problems
Try each problem on your own first, then compare with the solution.
Easy: Cinema Seat Booking
Write a class SeatBooking with fields movie, row and seat. Give it two constructors: a full one that takes all three values, and a short one that takes only the movie and books row "F", seat 10 by default. The short constructor must reuse the full one. Book "Space Trail" at row C seat 4, and "River Song" with the default seat, then print both.
Expected output:
textSpace Trail: C4 River Song: F10
Show answerHide answer
this. to fill fields that share names with the parameters.javaclass SeatBooking { private final String movie; private final String row; private final int seat; SeatBooking(String movie, String row, int seat) { this.movie = movie; this.row = row; this.seat = seat; } SeatBooking(String movie) { this(movie, "F", 10); } void print() { System.out.println(movie + ": " + row + seat); } } public class CinemaDesk { public static void main(String[] args) { new SeatBooking("Space Trail", "C", 4).print(); new SeatBooking("River Song").print(); } }
Output:
textSpace Trail: C4 River Song: F10
Medium: Chained Playlist with a Listener
Build a Playlist class with a name and a list of songs. add(String song) must return the playlist so calls can be chained. Also write a Speaker class with a method play(Playlist p) that prints the playlist name and every song with its position. Add a method playOn(Speaker s) in Playlist that passes the current playlist to the speaker. Create "Road Trip", chain three songs, and play it.
Expected output:
textNow playing: Road Trip 1. Open Highway 2. Desert Wind 3. Last Exit
Show answerHide answer
this makes chaining possible, and passing this lets another object work with the current playlist.javaimport java.util.ArrayList; import java.util.List; class Speaker { void play(Playlist p) { System.out.println("Now playing: " + p.getName()); List<String> songs = p.getSongs(); for (int i = 0; i < songs.size(); i++) { System.out.println((i + 1) + ". " + songs.get(i)); } } } class Playlist { private final String name; private final List<String> songs = new ArrayList<>(); Playlist(String name) { this.name = name; } Playlist add(String song) { this.songs.add(song); return this; } void playOn(Speaker s) { s.play(this); } String getName() { return name; } List<String> getSongs() { return songs; } } public class MusicRoom { public static void main(String[] args) { new Playlist("Road Trip") .add("Open Highway") .add("Desert Wind") .add("Last Exit") .playOn(new Speaker()); } }
Output:
textNow playing: Road Trip 1. Open Highway 2. Desert Wind 3. Last Exit