this võtmesõna
Sissejuhatus
this märksõna on viide hetkel kasutuses olevale objektile - objektile, mille meetodit või konstruktorit parajasti välja kutsutakse.
See on viis, kuidas objekt saab viidata iseendale.
this märksõna kasutatakse peamiselt kahes olukorras:
- Isendimuutujate ja samanimeliste parameetrite eristamisel
- Käesoleva objekti argumendina edastamine teisele meetodile
Selle märksõna kasutamise mõistmine on oluline selge ja üheselt mõistetava koodi kirjutamiseks, eriti konstruktorites ja kapseldamisel.
Mis asi on this?
this on eriline viide (reference), mis osutab käesolevale objektile.
Igal isendimeetodil ja konstruktoril on kaudselt olemas this-viide.
this märksõna võib mõista kui viidet "praegusele objektile, millega ma töötan".
Näiteks:
class Student {
private String name;
// ...
public void printInfo() {
System.out.println(this.name); // "this" refers to the current Student object
}
}
Kasutusalad
Nimekonfliktide lahendamine
Kõige levinum kasutus this märksõnale on nimekonfliktide lahendamine isendimuutujate ja parameetrite või lokaalsete muutujate vahel.
Näiteks, kui parameetril on sama nimi isendimuutujale, siis parameeter "varjendab" isendimuutujat ehk peidab selle ära.
class Student {
private String name;
private int age;
public void setName(String name) {
name = name; // Which name? Both refer to the parameter!
}
}
Antud näites on nii isendimuutuja kui ka parameetri nimeks name.
Sel juhul isendimuutujat eiratakse ning selle väärtus jääb muutumata.
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.setName("Alice");
System.out.println(student.name); // null - the field was never set!
}
}
Seda saab lahendada this märksõnaga järgnevalt:
class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
// this.name = instance variable
// name = parameter
}
public String getName() {
return this.name; // Here this is optional
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.setName("Alice");
System.out.println(student.getName()); // Alice
}
}
Samuti on kood selgelt loetavam ning kergem on aru saada, millele name viitab.
Kuigi nimekonflikte oleks võimalik ka lahendada järgnevalt:
public void setName(String newName) {
name = newName;
}
siis levinud praktika on kasutada this märksõna, kui parameeter ja isendimuutuja on sama nimega. Põhjuseks on:
- Parameetritel peaksid olema neutraalsed kirjeldavad nimed
- Kood on paremini loetavam (
thisütleb ära, millega täpselt tegemist) - See on Java standardne konventsioon ehk üldiselt tunnustatud kooditava.
Isegi olukordades, kus this ei ole nõutud, võib seda kasutada, et selgelt märku anda, et kasutatakse isendimuutujat (kuid see on küll maitse küsimus ja seda otseselt nõutud pole).
this kasutamine konstruktorites
Konstruktorite puhul kasutatakse this märksõna kahel viisil.
Esimesel juhul nimekonfliktide lahendamiseks:
class Book {
private String title;
private String author;
private int pages;
private double price;
public Book(String title, String author, int pages, double price) {
this.title = title; // instance variable = parameter
this.author = author;
this.pages = pages;
this.price = price;
}
// ...
}
Ning klassi enda konstruktori välja kutsumiseks:
class Book {
private String title;
private String author;
private int pages;
private double price;
public Book(String title, String author, int pages, double price) {
this.title = title; // instance variable = parameter
this.author = author;
this.pages = pages;
this.price = price;
}
public Book(String title, int pages) {
this(title, "Unknown Author", pages, 0.0);
}
// ...
}
Viimase kohta saate täpsemalt lugeda siit.
Käesoleva objekti edastamine argumendina
this on võimalik ka kasutada olukorras, kus on vaja käesolevat objekti teisele meetodile argumendina edastada.
Näiteks:
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void enrollInCourse(Course course) {
course.addStudent(this); // Pass this student object to the course
}
// getters/setters
}
class Course {
private String courseName;
public Course(String courseName) {
this.courseName = courseName;
}
public void addStudent(Student student) {
System.out.println(student.getName() + " enrolled in " + this.courseName);
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student("Alice", 20);
Course course = new Course("Java Programming");
student.enrollInCourse(course); // Alice enrolled in Java Programming
}
}
Käesoleva objekti tagastamine (meetodite aheldamine)
Viimasena, this märksõna kasutatakse ka selleks, et objekti ennast tagastada.
Võtame näiteks StringBuilder klassi append meetodid.
append() ja appendLine() meetodid tagastavad objekti iseennast.
See võimaldab meetodeid üksteise järgi aheldada.
Järgnevas näites emuleerime neid meetodeid. Pange tähele, et siin näites kasutame sõne üles ehitamiseks += operaatorit.
Praktikas sedasi StringBuilder ei tööta ning seda võtet ei tohiks kasutada.
Siin on niimoodi tehtud, et mõtet selgemini edastada.
public class MyStringBuilder {
private String content = "";
MyStringBuilder append(String text) {
content += text;
return this; // Return the current object
}
MyStringBuilder appendLine(String text) {
append(text);
append("\n");
return this;
}
void print() {
System.out.println(content);
}
}
class Main {
public static void main(String[] args) {
MyStringBuilder sb = new MyStringBuilder();
// Method chaining - each method returns "this"
sb.append("Hello ")
.append("World")
.appendLine("!")
.append("Welcome to Java");
sb.print();
// Hello World!
// Welcome to Java
}
}
Iga meetod tagastab tulemusena this, mis võimaldab järgmist meetodit kutsuda välja sama objekti peal, tekitades nendest väljakutsetest ahela.
this ja staatilised meetodid
this märksõna ei saa kasutada staatilistes meetodites kuna viimased kuuluvad klassile, mitte kindlale objektile.
public class Calculator {
private int result;
public void instanceMethod() {
this.result = 10; // OK - instance method has access to "this"
}
public static void staticMethod() {
this.result = 10; // ERROR - static methods don't have "this"
}
}
Teisiti võiks seda sõnastada niimoodi - this märksõna ei saa kasutada, kui pole teada, millele this täpselt viitama peaks.