Java’s this
Keyword
Learning Objectives Covered
By the end of this lesson, you will be able to explicitly use a reference to the current object.
Learning Materials
Time Commitment
Approximately 35-40 minutes
Read (Approximately 15 minutes)
A Concise Example
public class MyThisTest {
private int a;
public MyThisTest() {
this(42); // calls the other constructor (must be the first line in the constructor)
}
public MyThisTest(int a) {
// assigns the value of the parameter a to the field of the same name
this.a = a;
}
public void doThingsWithThis() {
int a = 1; // local variable a
System.out.println(a); // refers to the local variable a
System.out.println(this.a); // refers to the field a
System.out.println(this); // refers to this entire object
}
@Override
public String toString() {
return "MyThisTest a= " + a; // refers to the field a
}
}
Below is some code that uses the MyThisTest class:
MyThisTest test1 = new MyThisTest();
test1.doThingsWithThis();
System.out.println();
MyThisTest test2 = new MyThisTest(27);
test1.doThingsWithThis();
If we were to execute the above code we would see the following in the console:
1
42
MyThisTest a = 42
1
27
MyThisTest a = 27
Watch (Approximately 5 minutes)
this keyword in Java (Watch only up to 03:48)
Try (Approximately 15 minutes)
Instructions: Carefully read and consider each question, then choose an answer by clicking it.
NOTE: Once you click on an answer choice, you will be presented with an explanation for that choice. Some questions may have more than one correct answer.
Question 1
When a local variable has the same name as one of the instance variables, the local variable shadows the instance variable inside the method block. Developers often do this in constructors so that they can use the most meaningful name for each parameter. Which lines of code should we fill in the constructor below with, so that the instance variables are properly assigned their values?
public class Loan {
private double interest;
private LoanType type;
public Loan(double interest, LoanType type) {
}
// More Loan code below
}
Choice A
interest = this.interest;
type = this.type;
interest = this.interest;
type = this.type;
INCORRECT
This would set the values of the parameters to the default value of the instance variables, 0.0 and null. The object’s instance variables would never get initialized
Choice B
interest = interest;
type = type;
interest = interest;
type = type;
INCORRECT
This would set the values of the parameters to their current values. The object’s instance variables would never get initialized.
Choice C
this.interest = this.interest;
this.type = this.type;
this.interest = this.interest;
this.type = this.type;
INCORRECT
This would set the values of the object’s instance variables to the current value of the instance variables, 0.0 and null.
Choice D
this.interest = interest;
this.type = type;
this.interest = interest;
this.type = type;
CORRECT
This would set the values of the object’s instance variables to the values being passed into the constructor.
Click here for further explanation
We want to initialize the class’ fields in the constructor so they should be on the left hand sign of the assignment statement, and the word this should be used to disambiguate from the constructor’s parameters. On the right hand side of the assignment operator we should use the parameters from the constructor. This should not be used, so the compiler knows to use the values being passed in to the constructor.
Question 2
Below we have a class for a circle.
public class Circle {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
public int getDiameter() {
return radius * 2;
}
public double getArea() {
return Math.PI * Math.pow(radius, 2);
}
}
We want to allow users of our class to graph the circle, so we will keep a track of the x, y coordinates of the circle’s center. We will use a Point object to do this. Below we have updated the Circle class, adding a field of type Point and a constructor to initialize both the center and the radius.
public class Circle {
private int radius;
private Point center;
public Circle(int radius) {
this.radius = radius;
}
public Circle(int radius, Point center) {
this.radius = radius;
this.center = center;
}
public int getDiameter() {
return radius * 2;
}
public double getArea() {
return Math.PI * Math.pow(radius, 2);
}
}
However, now if a user of the class uses the Circle(int radius)
constructor, the point instance variable will be null
. Select all of the below choices that we could replace the existing Circle(int radius)
constructor with that will initialize the center to a point located at (0, 0)
.
Choice A
public Circle(int radius) {
this(0, 0, radius);
}
public Circle(int radius) {
this(0, 0, radius);
}
INCORRECT
The code uses this to call a Circle constructor with three arguments. However, there is no constructor defined that accepts three parameters.
Choice B
public Circle(int radius) {
this.radius = radius;
Point center = new Point(0, 0);
this.center = center;
}
public Circle(int radius) {
this.radius = radius;
Point center = new Point(0, 0);
this.center = center;
}
CORRECT
The code creates a new Point and directly assigns it to the center field.
Choice C
public Circle(int radius) {
this.radius = radius;
Point point = new Point(0, 0);
center = point;
}
public Circle(int radius) {
this.radius = radius;
Point point = new Point(0, 0);
center = point;
}
CORRECT
The code does the same thing as B, but uses a different name for the new point, point. Here this is not required before center, as point is a different variable name and the statement
center = point;
is not ambiguous. Even though not required, we would probably use it anyway to match the style of the above assignment statement.
this.radius = radius;
Point point = new Point(0, 0);
this.center = point;
Choice D
public Circle(int radius) {
this(radius, new Point(0,0));
}
public Circle(int radius) {
this(radius, new Point(0,0));
}
CORRECT
The code correctly uses this to call the existing constructor of the Circle class, passing to it the radius and a newly created Point object.
Question 3
Take a look at the class PracticeThis.
public class PracticeThis {
private String str;
public PracticeThis() {
this("NSS Rulez");
}
public PracticeThis(String str) {
this.str = str;
}
public void practiceMyThisKnowledge() {
String str = "Who says NSS Rulez?";
System.out.println(str);
System.out.println(this);
}
@Override
public String toString() {
return "According to PracticeThis: " + str;
}
}
Predict what will be printed when the following lines of code are executed:
PracticeThis thisPractice = new PracticeThis();
thisPractice.practiceMyThisKnowledge();
Choice A
NSS Rulez
According to PracticeThis: NSS Rulez
NSS Rulez
According to PracticeThis: NSS Rulez
INCORRECT
System.out.println(str);
The above statement is ambiguous, as there are two variables named str. However, as the this keyword is not used it will print the local variable named str, and not the instance variable.
Choice B
Who says NSS Rulez?
According to PracticeThis: NSS Rulez
Who says NSS Rulez?
According to PracticeThis: NSS Rulez
CORRECT
System.out.println(str);
The above statement is ambiguous, as there are two variables named str. However, as the this keyword is not used it will print the local variable named str, and not the instance variable.
return "According to PracticeThis: " + str;
The above use of str is not ambiguous. The method only knows about the instance variable named str, and so it is not necessary to use the this keyword. The this keyword, could be optionally used here and still correct:
return "According to PracticeThis: " + this.str;
Choice C
Who says NSS Rulez?
According to PracticeThis: Who says NSS Rulez?
Who says NSS Rulez?
According to PracticeThis: Who says NSS Rulez?
INCORRECT
return "According to PracticeThis: " + str;
The above use of str is not ambiguous. The str defined in practiceMyThisKnowledge()
is no longer visible within the toString()
. The scope is confined to within the method it is declared.
Question 4
Consider the RatingScore class.
public class RatingScore {
private double rating;
private int maxRating;
private String description;
public RatingScore(double rating, int maxRating) {
this(rating, maxRating, "");
}
public RatingScore(double rating, int maxRating, String ratingDescription) {
this.rating = rating;
this.maxRating = maxRating;
this.description = ratingDescription;
}
public String getRatingDescription() {
return description;
}
public String getDisplayableRating() {
return rating + " out of " maxRating;
}
}
When initializing this class, it is required to provide a maxRating
value, however the rating
value can default to 0, and the description
may default to an empty String. Review the four constructors defined below that accept the single required parameter, maxRating
. Select all that are valid Java syntax.
Choice A
public RatingScore(int maxRating) {
this(0.0, maxRating, "");
}
public RatingScore(int maxRating) {
this(0.0, maxRating, "");
}
CORRECT
This new constructor calls an existing constructor by using this. It passes the new value for maxRating, and the default values for rating and description.
Choice B
public RatingScore(int maxRating) {
this.maxRating = maxRating;
this(0.0, "");
}
public RatingScore(int maxRating) {
this.maxRating = maxRating;
this(0.0, "");
}
INCORRECT
A call to an existing constructor using this must be the first statement in the constructor.
Choice C
public RatingScore(int maxRating) {
this(0.0, maxRating);
}
public RatingScore(int maxRating) {
this(0.0, maxRating);
}
CORRECT
A call to an existing constructor using this is the first statement. The two parameter constructor is called with the default value for rating plus the required argument, maxRating
.
Choice D
public RatingScore(int maxRating) {
this.maxRating = maxRating;
this.description = "";
this.rating = 0;
}
public RatingScore(int maxRating) {
this.maxRating = maxRating;
this.description = "";
this.rating = 0;
}
CORRECT
It is a good practice to use this to call another constructor that already does the assignments you are looking to write, but not necessary. It is good practice because if parameter validations are added to a constructor it only needs to be done once and shared, rather than added to each constructor.