0

When I read spring source code, class "AbstractApplicationContext" has a field:

private String id = ObjectUtils.identityToString(this);

I have a doubt, method identityToString(this) is executed before class AbstractApplicationContext is instantiated. Why "this" keyword can be used at this time?

As I understand, this represents the AbstractApplicationContext instance, before AbstractApplicationContext is instantiated, this cannot be used.

Can someone answer my doubts?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
17u
  • 13
  • 1
  • 1
    You might want to check https://stackoverflow.com/questions/14805547/are-fields-initialized-before-constructor-code-is-run-in-java – Progman Jul 05 '22 at 17:16
  • 2
    It is not _"executed before class AbstractApplicationContext is instantiated"_, it is executed during initialization, the object represented by `this` already exists at that point (it might just not be fully initialized). – Mark Rotteveel Jul 05 '22 at 17:16
  • 2
    it is explicitly allowed in the [Java Language Specification 15.8.3](https://docs.oracle.com/javase/specs/jls/se18/html/jls-15.html#jls-15.8.3-100-D): "**The keyword this may be used as an expression in the following contexts:** ... in the initializer of an instance variable of a class" ||| BTW the instance is being initialized at that specific moment, and the first step is allocating memory, before executing any code, so `this` already got its value (reference) ||| sure, such call is dangerous and eventually cause problems – user16320675 Jul 05 '22 at 17:18

1 Answers1

0

There are different stages in class loading and object instantiating. Let's look at the latter, because this is interesting for you.

The following steps are executed:

  1. A memory area is allocated for the object. It has a reference, it will be associated with the newly created object. It is the this reference, and as you can see, it works from the very first step.
  2. Then all the fields are initialized and all the instance blocks are run (these are the { } blocks within the class definition). If starts with the Object class, then in all descendant classes, lastly the instantiated class.
  3. Finally the constructor is called - it is not constructing the object, opposing to its name, it only initializes it, with the given parameters. The constructor calls the super constructor as the first step - ultimately the Object constructor is executed first, then the descendants, lastly the constructor of the instantiated class.

Actually it's a bad technique to access this before the end of the constructor, it even has a name: leaking this.

gaborsch
  • 15,408
  • 6
  • 37
  • 48
  • 1
    step 1.5: explicit/implicit call of superclass constructor(s) (and same steps 1.5, 2 and 3 for that superclass) unless the class is `Object` - [JLS 12.5](https://docs.oracle.com/javase/specs/jls/se18/html/jls-12.html#jls-12.5) – user16320675 Jul 05 '22 at 17:43
  • @user16320675 Thanks for the addendum, it's partly true. The fields are initialized, but the constructor is called at step 3 - that's why the `super` call must be the first call in each constructor. (There may be multiple super constructors). Changed the text. – gaborsch Jul 05 '22 at 17:54
  • "partly true" - what exactly is wrong? the superclass constructor is executed before the fields and instance initializers of the current class is executed (sure it is even more complicated, some steps/cases omitted...) – user16320675 Jul 05 '22 at 18:10
  • BTW simple prove on [IDEone](https://ideone.com/atYyZM) - we see that the super constructor is called before step 2 ! Otherwise the Java Language Specification - I added the [link](https://docs.oracle.com/javase/specs/jls/se18/html/jls-12.html#jls-12.5) in first comment - is wrong... probably since last millennium (?) ||| kind of *logial* to have the superclass fully initialized before starting to initialize the child class – user16320675 Jul 05 '22 at 18:19