• Post Reply Bookmark Topic Watch Topic
  • New Topic

'this' inside constructor  RSS feed

 
Shouvik Bhattacharya
Ranch Hand
Posts: 40
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In snippet below is the use of 'this' acceptable.

How is 'this' available inside the constructor when the object represented by it is yet not constructed?
 
Dave Tolls
Ranch Foreman
Posts: 3001
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The object exists before the constructor is executed, with default values for its attributes (0's, null's, false).
 
Shouvik Bhattacharya
Ranch Hand
Posts: 40
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:The object exists before the constructor is executed, with default values for its attributes (0's, null's, false).


Unless the constructor finishes its execution how can it exist?
 
Campbell Ritchie
Marshal
Posts: 56202
171
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
DT is correct; the object exists in an inchoate state; shoul‍d the constructor fail to complete normally, the line of code calling it will also fail to complete normally because of the Exception.This is \u2019: ’
Here somebody made the mistake of not giving that constructor private access (see the Java┬« Language Specification =JLS). Line 1 invokes the new operator to create a Foo object and then control enters that constructor. The solitary statement in that constructor completes abruptly because of the exception, which propagates to line 1. When line 1 fails to complete normally because of the exception, the program state is wound back to what it had been before that line, which means the Foo object is destroyed.
This part of the JLS tells you that the object exists before the constructor runs.
 
Stephan van Hulst
Saloon Keeper
Posts: 7928
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This adds another issue that you have to be very careful about: Because the object exists, but is not in a consistent state yet, you have to be *very* careful about where the reference to the object being constructed escapes to. In general, from the constructor

  • don't pass 'this' to methods of other classes,
  • don't call methods of the current class unless they are private, final or static
  • don't start new threads, and
  • don't call private, final or static methods that indirectly do any of the previous three points.
  •  
    Shouvik Bhattacharya
    Ranch Hand
    Posts: 40
    Eclipse IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Stephan van Hulst wrote:
  • don't call methods of the current class unless they are private, final or static
  • don't start new threads, and

  • Can you please elaborate a bit on this why this is so.
     
    Campbell Ritchie
    Marshal
    Posts: 56202
    171
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    A long time ago, I commented on a post where a Pupil object was being initlalised. It looked something like this:-What is going to happen if you run that sort of code in a threaded environment? What if you are reading data from a database as you create those objects? What if you have some but not all the data for a particular Pupil object? The Threads are permitted to take the different statements in the constructor out of order, and execute line 6 before 3 4 or 5. Now you have a Pupil object registered at a School with incomplete information. Think what could go wrong. You could have 10,000,000 pupils in 50,000 schools (a likely number for many European countries); if there is a 1 in a million chance of such an error, there is a 99.995+% chance of there being an error in one of those schools. Think how long it would take to find, remembering that it is highly likely there are multiple errors. But nobody knows how many.
     
    Campbell Ritchie
    Marshal
    Posts: 56202
    171
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If you override a method in a subclass, that is the method called if you create a subclass.You need the -ea flag when you run that code, otherwise the assert statement won't be executed.
    If you call the subclass constructor, you get the overridden version. The creator of the Year class might not know that some naughty person has overridden a method, or had a good reason to override it. Anyway, whatever happens you will get a result completely different from what you expected. If the method in line 9 had private access, then the method in line 108 would be a completely new and unrelated method. If the method in line 9 were marked final, line 108 wouldn't compile. In either case, this problem would never have arisen. Static methods are bound to the declared class name, so a static method in that line 201 call would be bound to the Year class and never the subclass. Again, no problem.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7928
    143
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Stephan van Hulst wrote:
  • don't call methods of the current class unless they are private, final or static

  • Campbell already illustrated this. Here's another example:

    Now, let's create a sub-class that ensures that when you change the name of a person, it is not the same as the old name:

    The problem here is that when you construct a new PersonWithNameChangeRules, it will always throw a NullPointerException. This is because the overridden setName() method assumes that the object is in a consistent state (meaning it already has an old name), but because it's being called from the constructor, this.name() still returns null. Methods that are private, final or static don't have this problem, because they can't be overridden.

  • don't start new threads

  • The reason is twofold. First of all, it's just really confusing when background operations start happening when all you're doing is create a new object. I expect a constructor call to just give me a new object, and do nothing more. The second reason is that it's very easy to expose a reference to the current object to a thread. That thread will then see the object in an inconsistent state:

    Even though callAllPhoneNumbers() is final (because the entire class is final), it may still see the current object in an inconsistent state, because the thread that calls it may not see that message and phoneNumbers have been initialized yet, even if you started the thread after you assigned values to the two fields. The reason for this is very complex, and has to do with Java's memory model. You could solve this by making the constructor thread-safe, but I believe that Bruce Eckel wrote a very detailed explanation why you can't really make constructors thread-safe.
     
    Shouvik Bhattacharya
    Ranch Hand
    Posts: 40
    Eclipse IDE Java
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I was a bit sceptical while asking this question, I thought maybe I was asking something way to simple to understand. But now I feel elated having asked this question. There was a lot to learn from it. I am really thankful to this wonderful community.
    Cheers! and thank you for sharing some wonderful knowledge.
     
    Campbell Ritchie
    Marshal
    Posts: 56202
    171
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Often the simplest questions give the best answers.
     
    It is sorta covered in the JavaRanch Style Guide.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!