杰瑞科技汇

Java中return this到底有什么用?

Of course! In Java, the keyword this is a reference to the current object—the object whose method or constructor is being called.

Java中return this到底有什么用?-图1
(图片来源网络,侵删)

Using return this; is a common and powerful technique, especially in the context of method chaining (also known as a "fluent interface"). Let's break down what it means and why you'd use it.


What return this; Means

When you write return this; inside a method, you are returning a reference to the very same object that the method was called on.

Think of it like this: if you have a Car object named myCar, and you call a method on it like myCar.setColor("red"), then this inside that setColor method refers to myCar. If the setColor method ends with return this;, it's returning the exact same myCar object.

The Primary Use Case: Method Chaining

This is the most common and important reason to use return this;. Method chaining allows you to call multiple methods on the same object in a single, continuous statement.

Java中return this到底有什么用?-图2
(图片来源网络,侵删)

Without Method Chaining (The "Verbose" Way)

Imagine a Person class with setters.

class Person {
    private String name;
    private int age;
    private String city;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setCity(String city) {
        this.city = city;
    }
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";
    }
}
public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("Alice");
        person.setAge(30);
        person.setCity("New York");
        System.out.println(person);
    }
}

Output:

Person{name='Alice', age=30, city='New York'}

This works, but it requires three separate lines to configure the object.

With Method Chaining (Using return this;)

Now, let's modify the setters to return this.

class FluentPerson {
    private String name;
    private int age;
    private String city;
    // The 'setter' methods now return 'this'
    public FluentPerson setName(String name) {
        this.name = name;
        return this; // Return the current object
    }
    public FluentPerson setAge(int age) {
        this.age = age;
        return this; // Return the current object
    }
    public FluentPerson setCity(String city) {
        this.city = city;
        return this; // Return the current object
    }
    @Override
    public String toString() {
        return "FluentPerson{name='" + name + "', age=" + age + ", city='" + city + "'}";
    }
}
public class Main {
    public static void main(String[] args) {
        FluentPerson person = new FluentPerson()
            .setName("Alice")       // setName() returns the FluentPerson object
            .setAge(30)             // setAge() is called on the returned object
            .setCity("New York");   // setCity() is called on the returned object
        System.out.println(person);
    }
}

Output:

FluentPerson{name='Alice', age=30, city='New York'}

Notice how much cleaner the main method is! The code reads like a sentence: "Create a new FluentPerson, set its name to 'Alice', set its age to 30, and set its city to 'New York'."

How it Works: A Step-by-Step Breakdown

Let's trace the execution of the chained call:

  1. new FluentPerson(): A new FluentPerson object is created in memory. Let's call its reference obj1.
  2. .setName("Alice"): This method is called on obj1.
    • Inside setName, this refers to obj1.
    • The name is set to "Alice".
    • return this; is executed, which returns the reference obj1.
  3. .setAge(30): The result of the previous call (obj1) is used to call this method. So, setAge(30) is called on obj1.
    • Inside setAge, this refers to obj1.
    • The age is set to 30.
    • return this; is executed, which again returns the reference obj1.
  4. .setCity("New York"): The result of the previous call (obj1) is used to call this method. So, setCity("New York") is called on obj1.
    • Inside setCity, this refers to obj1.
    • The city is set to "New York".
    • return this; is executed, which returns the reference obj1.
  5. The final expression evaluates to obj1, which is then assigned to the person variable.

Other (Less Common) Use Cases for return this;

While method chaining is the star, there are other scenarios where you might return this.

a) In Constructors

You can use return this; in a constructor to provide a default or alternative object. This is less common for simple constructors but can be useful in builder patterns or when a constructor might decide to return a cached or different instance.

class Car {
    private String model;
    public Car(String model) {
        this.model = model;
    }
    // A constructor that might return a different object
    public Car createDefaultCar() {
        if (this.model == null || this.model.isEmpty()) {
            // If the model is not set, return a new default car instead
            return new Car("Default Model");
        }
        // Otherwise, return the current object
        return this;
    }
}

b) To Return the Current Object from a Non-"Setter" Method

Any method that modifies the object and is intended to be part of a chain can return this.

class StringBuilderExample {
    private StringBuilder sb = new StringBuilder();
    public StringBuilderExample append(String text) {
        sb.append(text);
        return this; // Allow chaining
    }
    public StringBuilderExample toUpperCase() {
        String current = sb.toString();
        sb = new StringBuilder(current.toUpperCase());
        return this; // Allow chaining
    }
    @Override
    public String toString() {
        return sb.toString();
    }
}
public class Main {
    public static void main(String[] args) {
        String result = new StringBuilderExample()
            .append("hello ")
            .append("world")
            .toUpperCase()
            .toString();
        System.out.println(result); // Output: HELLO WORLD
    }
}

Key Takeaways

  • this: A reference to the current object instance.
  • return this;: Returns a reference to the very same object the method was called on.
  • Main Purpose: To enable method chaining, resulting in more readable, concise, and "fluent" code.
  • Common Pattern: Used in "setter" methods of builder classes or configuration objects.
  • Not Always Needed: You should only use return this; if you have a specific reason, like enabling chaining. If a method is a simple "getter" or performs an action that doesn't logically lead to another call on the same object, it should typically return void or a relevant value (like a primitive or a different object).
分享:
扫描分享到社交APP
上一篇
下一篇