96

Is it good/bad/acceptable practice to pass the current object in a method call. As in:

public class Bar{
    public Bar(){}

    public void foo(Baz baz){
        //  modify some values of baz
    }
}

public class Baz{
    //constructor omitted

    public void method(){
        Bar bar = new Bar();
        bar.foo(this);
    }
}

Specifically, is the line bar.foo(this) acceptable?

10
  • 60
    Why would that not be acceptable ? It's common. Commented Jul 3, 2013 at 7:15
  • 3
    So... that's 8 yes's :) (And yes, i'm keeping it updated.) Commented Jul 3, 2013 at 7:18
  • 2
    non-static anonymous class automatically pass this reference of the super class, so this will be acceptable. the only caution would be to careful about circular references. Commented Jul 3, 2013 at 7:18
  • 6
    There is one caveat though: you shouldn't pass this in constructor because that'd expose your object in an inconsistent state. People typically do that when they create callbacks (e.g. ActionListener) as anonymous inner classes and then pass that to another object.
    – Tamas Rev
    Commented Jul 3, 2013 at 11:02
  • 3
    @dystroy although I agree it is acceptable, implying that it is acceptable because it is common is really bad logic. Doing something because its common can get you into a lot of trouble Commented Jul 3, 2013 at 15:18

10 Answers 10

166
+250

There's nothing wrong with that. What is NOT a good practice is to do the same inside constructors, because you would give a reference to a not-yet-completely-initialized object.

There is a sort of similar post here: Java leaking this in constructor where they give an explanation of why the latter is a bad practice.

10
  • 18
    +1: good to point out the hazard in referring to 'this' in constructors.
    – Bathsheba
    Commented Jul 3, 2013 at 7:19
  • It is not necessarily a bad practice. For example, a Car constructor may create Wheel instances, a Car without Wheel would be incompletely initialized, while a Wheel without a corresponding Car would also be incompletely initialized. In this case, it may be acceptable in the Car's constructor to pass this to the Wheel's constructor. The other alternative would be to make both Car and Wheel have private constructor and use a factory function that constructs the Car, Wheel, and installs the Wheel on the Car; but should that be a static method on Car or static method on Wheel?
    – Lie Ryan
    Commented Jul 3, 2013 at 13:34
  • Obviously, you should create a CarFactoryWheelInstallerProxy that installs the wheels for you.
    – Kevin
    Commented Jul 3, 2013 at 15:26
  • 6
    @LieRyan Wheel is completely subordinate to Car, and IMO shouldn't know about Car at all.
    – Izkata
    Commented Jul 3, 2013 at 17:22
  • 3
    The ONLY bad thing about using this from within a constructor is if this is passed into a method or context from which the not-yet-fully-contructed object reference is published to untrusted or unknown clients (or client code that assumes it has a view to a fully constructed object). Passing this from a constructor to a package-private method that performs a common initialization is, in my opinion, not only acceptable but desirable.
    – scottb
    Commented Jul 3, 2013 at 17:26
155

There's no reason not to use it, this is the current instance and it's perfectly legitimate to use. In fact there's often no clean way to omit it.

So use it.

As it's hard to convince it's acceptable without example (a negative answer to such a question is always easier to argument), I just opened one of the most common java.lang classes, the String one, and of course I found instances of this use, for example

1084        // Argument is a String
1085        if (cs.equals(this))
1086            return true;

Look for (this in big "accepted" projects, you won't fail to find it.

7
  • 16
    -1 because there is no mention of the fact that bi-directional class relationships are more complicated than uni-directional relationships. It is vital to ensure that software is clear as possible. In the specific example above it would be more sensible to Move Method foo to the Baz class to avoid having a bi-directional reference between the two classes and to bring the behaviour and the data together.
    – JW.
    Commented Jul 3, 2013 at 16:38
  • 39
    -1 to an answer because you found in the question an additional minor detail on which you can comment ? Really ? Commented Jul 3, 2013 at 16:41
  • 2
    @dystroy No. I gave -1 because it is important to avoid bi-directional links if possible. Hence, I completely disagree with the answer. That's what the downvote is for.
    – JW.
    Commented Jul 3, 2013 at 17:10
  • 13
    @dystroy Yes I disagree with your opening phrase: "There's no reason not to use it".
    – JW.
    Commented Jul 3, 2013 at 17:12
  • 4
    In practice, in real code (contrary to OP's simplified example), passing this doesn't mean you add a bidirectional link, because of inheritance and interfaces for example. Commented Jul 3, 2013 at 17:17
42

Yes, but you should be careful about two things

  1. Passing this when the object has not been constructed yet (i.e. in its constructor)
  2. Passing this to a long-living object, that will keep the reference alive and will prevent the this object from being garbage collected.
3
  • 1
    Note that a constructor in Java is not really a constructor, it's probably more appropriate to call Java's constructor "initializer". Within Java constructor, the object has actually been allocated memory, this the object actually has already existed/constructed within the constructor.
    – Lie Ryan
    Commented Jul 3, 2013 at 21:15
  • 1
    Not really, the object may have some instance variables that have not been initialised yet, so that the object is not fully operative yet. So, in the constructor, you could pass this to a second object, that could invoke a method to the object that has not initialized all its instance variables yet. Commented Jul 3, 2013 at 23:11
  • yet, as long as the second object are aware that the passed object isn't initialized, and treats it as an opaque object, or only call methods that have been declared safe in such state, it will cause no problem to pass this to it. Doing that would have been impossible if the object hasn't been allocated.
    – Lie Ryan
    Commented Jul 4, 2013 at 0:49
13

It's perfectly normal and perfectly acceptable.

5

this stands for the current object. What you are doing is sytatically correct but i don't see a need of this if you are calling the method in the same class.

2
  • 2
    In the example code, Baz.method() is an instance method which calls Bar.foo() with the instance of Baz as a parameter. So the OP is not calling a method in the same class.
    – user
    Commented Jul 3, 2013 at 9:12
  • @MichaelKjörling I think Juned is saying that, by moving the foo() method into the Baz class, there would be no need to pass this between the two classes. So, there is no need to add the extra complexity.
    – JW.
    Commented Jul 3, 2013 at 16:44
5

It is bad practice to pass the current object in a method call if there less complex alternatives to achieve the same behaviour.

By definition, a bidirectional association is created as soon as this is passed from one object to another.

To quote Refactoring, by Martin Fowler:

Change Bidirectional Association to Unidirectional (200)

Bidirectional associations are useful, but they carry a price. The price is the added complexity of maintaining the two-way links and ensuring that objects are properly created and removed. Bidirectional associations are not natural for many programmers, so they often are a source of errors

...

You should use bidirectional associations when you need to but not when you don’t. As soon as you see a bidirectional association is no longer pulling its weight, drop the unnecessary end.

So, theoretically, we should be hearing alarm bells when we find we need to pass this and try really hard to think of other ways to solve the problem at hand. There are, of course, times when, at last resort, it makes sense to do it.

Also it is often necessary to corrupt your design temporarily, doing 'bad practice things', during a longer term refactoring of your code for an overall improvement. (One step back, two steps forward).

In practice I have found my code has improved massively by avoiding bidirectional links like the plague.

5
  • You confuse a simplified example with the need to establish a bidirectional link. Passing this as parameter, as should be clear with many examples of the java.lang source code (for example the one you saw in my answer) doesn't mean you add a bidirectional dependency. This answer should have been a comment in my opinion. Commented Jul 3, 2013 at 17:19
  • @dystroy Thanks for adding a comment to explain why you downvoted. Its always good to know. I shall modify my answer to clarify that, by definition, a bidirectional association is created as soon as this is passed.
    – JW.
    Commented Jul 3, 2013 at 17:24
  • 1
    "by definition, a bidirectional association is created as soon as this is passed". This makes clear where you fail to understand. Look at the example I give. There is no bidirectional link because the type of the argument in equals is Object. This is very common : the receiving method defines its argument as a more general class or as an interface. One of the reason such a pattern is used in java is to avoid unwanted dependencies. Before going longer I'd suggest you take a look at the many occurrences of passing this as argument in respectable java libraries. Commented Jul 3, 2013 at 17:37
  • Let's just agree to disagree. My life has become much easier since I have avoided passing this in my code, where possible. I'd recommend others to do so.
    – JW.
    Commented Jul 3, 2013 at 17:45
  • 2
    @JW: the reasoning given in this answer is irrelevant. It's always a bad idea to do X if there's something else that's simpler, for any value of X.
    – Lie Ryan
    Commented Jul 4, 2013 at 1:40
4

Yes. you can use it.Its just common in programming to pass this.But there are pros and cons about using that.Still it is not hazardous to do so.

2
  • There are plenty of side effects. It adds complexity.
    – JW.
    Commented Jul 3, 2013 at 16:41
  • If those many side effects are there we couldn't find a single evidance like that in our java source code .see @destroys example from source code. Commented Jul 3, 2013 at 19:48
2

Just to add one more example where passing this is correct and follows good design: Visitor pattern. In Visitor design pattern, method accept(Visitor v) is typically implemented in a way it just calls v.visit(this).

1

Acceptable

Snippet from Oracle JAVA docs:

Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.

Using this with a Field

The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.

2
  • 2
    "You can refer to any member of the current object" -- that does not seem to answer the question "is it acceptable to pass this as a parameter?".
    – user
    Commented Jul 3, 2013 at 9:10
  • 2
    This is saying how you can do this.some_variable to refer to the class variable instead of to a local variable. It has nothing to do with passing this as a parameter. Commented Jul 3, 2013 at 12:27
0

Everything in java is passed by value. But objects are NEVER passed to the method!
When java passes an object to a method, it first makes a copy of a reference to the object, not a copy of the object itself. Hence this is pefectly used method in java. And most commonly followed usage.

7
  • 4
    "Everything in java is passed by value." - that's a very misleading initial comment. Actually all objects are passed by reference and all primitive types are passed by value. You've NEVER have a this reference to a primitive type, and therefore I think your "more info" is introducing confusion.
    – Stewart
    Commented Jul 3, 2013 at 11:05
  • 1
    @Stewart: He immediately makes it clear that he doesn't mean that whole objects are copied.
    – LarsH
    Commented Jul 3, 2013 at 13:34
  • 10
    @Stewart no, objects are not passed by reference, rather object references are passed by value. It's an important distinction - pass by reference would mean that if I have a local variable that refers to an object and pass that variable to another method, the method would be able to change which object my variable refers to, and this is definitely not something you can do in Java. The method can mutate the state of the object through its own copy of the reference but it can't change my copy of the reference to point to something else. Commented Jul 3, 2013 at 13:54
  • @Ian I've never heard of any other definition of "pass by reference" except what you've just described - ie, a reference (pointer) is the value passed. With regard to this question we can say Object that = this; and then this and that are different references to the same object. Whichever one you pass into a method, inside the method you'd have a 3rd reference to the same object.
    – Stewart
    Commented Jul 3, 2013 at 16:28
  • 2
    @Stewart yoda.arachsys.com/csharp/parameters.html is a good article that explains the difference between passing by reference and passing references by value, in the context of C# which supports both. Commented Jul 3, 2013 at 16:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.