• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Lost and confused, p. 129 (K&B7)

 
Mark Kevin
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I can't make sense of the last bullet which reads, "The only way a constructor can be invoked is from within another constructor." I understand it can't be called from within the method doStuff(), but what does "from within another constructor" mean? Is there an example of this somewhere? What kind of other constructor?
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Kevin wrote:I understand it can't be called from within the method doStuff(), but what does "from within another constructor" mean? Is there an example of this somewhere? What kind of other constructor?

If you invoke it from within another method, you must use the keyword new and you will create a new instance. Without the keyword new, you will get a compiler error.
You can invoke another constructor using keywords this (for another constructor in same class) or super (for another constructor in parent class). But these calls are only allowed from within another constructor (so not in a method) and must be the first statement of the constructor. Otherwise you will get a compiler error as well.

Hope it helps!
Kind regards,
Roel
 
Paweł Baczyński
Bartender
Posts: 1878
35
Firefox Browser IntelliJ IDE Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And at least one constructor must call a constructor of the superclass (it can be an implicit call).
 
Mark Kevin
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks to both of you. I agree and understand your explanations. I just don't understand how 'invoking a constructor from within another method using new' is considered "from within another constructor," (which doesn't always invoke this()). It seems the sentence in the text would have been clearer and more accurate if it added, "or from within another method if you use the keyword 'new,' just like you said. And come to think of it, technically, even if you add the word new when invoking it in a method, it's still not being invoked "from within another constructor." This wording really threw me off.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Kevin wrote:It seems the sentence in the text would have been clearer and more accurate if it added, "or from within another method if you use the keyword 'new,' just like you said.

Definitely not! And the statement as-is is 100% accurate as well.

The bullet point you are mentioning is one of many in the section "Rules for Constructors". The one and only thing this statement is trying to explain is: you can only invoke a constructor from within another constructor. You can't invoke a constructor from a method, a (static) initializer block, and so on. And that's also what the accompanying code snippet and this code snippet illustratesAnd that's really the only thing this bullet point wants to emphasize. So it's not about how to create new instances (new Constructor();), that's why your suggested addition would not be an improvement. It's all about from where you can invoke a constructor. And that's only allowed from within another constructor (using this or super). So you could argue that changing the sentence into "The only way a constructor can be invoked is from within another constructor (using this or super as the first statement)." might be an improvement. But the part in between parantheses is already mentioned in the second bullet point of this page.

Here is a bonus question: how can you make the Constructor class successfully compile with changing only one line?

Hope it helps!
Kind regards,
Roel
 
Mark Kevin
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

"The only way a constructor can be invoked is from within another constructor (using this or super as the first statement)."


That seems to make more sense. So what the book is saying is that every new constructed object has to go through this() or super().

So let me get this straight. If I call a constructor from another method (new newConstructor(), and it invokes newConstructer() which has super() as its first statement, then, after the superclass is created the superclass somehow passes control back to the subclass and invokes the subclass constructor, the original constructor newConstructor().

I think the part that threw me was "invoked." And, the words "from another constructor." If super() gets called, then something in the superclass must eventually invoke the constructor in the subclass. If this() is called, then it's almost recursive in a way and it calls this no-argument constructor, or one with arguments. So I understand the this() part of it which makes sense.

And I'll just assume that after super() runs, it invokes the subclass constructor, which it must, otherwise there's no "another constructor" invoking it. Sorry to be so dense, but I really have tried to put some thought into this.

I suppose whether its super() or this(), either of these is an "invocation from within a constructor." And I should assume that the superclass constructor ultimately invokes the subclass constructor.

In other words, with respect to super(), "from within another constructor" must refer to "from within the superclass" constructor somewhere. The subclass constructor gets invoked from within the superclass constructor (which is the "another constructor" of the last bullet). (And the superclass constructor must run before the subclass constructor runs). The subclass constructor with super() is not "another constructor" and the only other constructor remaining would be the superclass constructor. That's a tongue twister.


 
Mark Kevin
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is a bonus question: how can you make the Constructor class successfully compile with changing only one line?


Stumped. I tried all sorts of things. If I add 'new' to the call it compiles, but I would have to do that on two lines, not one. Any hints?



 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Kevin wrote:If I add 'new' to the call it compiles, but I would have to do that on two lines, not one.

That's indeed the easy fix. And you could remove both new Constructor(); lines as well or put them into comments

Mark Kevin wrote:Any hints?

Sure! Have a close look at the compiler error you get after compiling the Constructor class.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Kevin wrote:That seems to make more sense. So what the book is saying is that every new constructed object has to go through this() or super().

Yes! And that's either explicitly (if you add a specific call to this() or super()) or implicitly (if you don't add any call, and the compiler adds it for you). There is one big exception to this rule: the Object class, its constructor doesn't have a call to this() or super() because it's the root of the class hierarchy. Every class has Object as a superclass.

Mark Kevin wrote:So let me get this straight. If I call a constructor from another method (new newConstructor(), and it invokes newConstructer() which has super() as its first statement, then, after the superclass is created the superclass somehow passes control back to the subclass and invokes the subclass constructor, the original constructor newConstructor().

First of all, there is no such thing as "creating the (super)class". You as a developer create a (super) class (like I did with the Constructor class in my previous post). When the class is required when running an application, the class is loaded (and initialized) by the JVM. This class can be used to access static members and/or to create instances of this class. Secondly, it's the subclass constructor which invokes the parent class constructor; when the parent class constructor is finished, the control goes automatically back to the subclass constructor (cf. with method calls). Let's illustrate with a code exampleline1 creates only one (1) object! And to create this object, the following steps are executed (in this order):
  • main() invokes new C() => C() constructor is invoked
  • C() explicitly invokes C(int) => C(int) constructor is invoked
  • C(int) implicitly invokes super() => B() constructor is invoked
  • B() implicitly invokes super() => A() constructor is invoked
  • A() implicitly invokes super() => Object() constructor is invoked
  • Object() constructor completes
  • A() constructor completes
  • B() constructor completes
  • C(int) constructor completes
  • C() constructor completes
  • The new C instance is created and ready to be used


  • Mark Kevin wrote:I think the part that threw me was "invoked." And, the words "from another constructor." If super() gets called, then something in the superclass must eventually invoke the constructor in the subclass. If this() is called, then it's almost recursive in a way and it calls this no-argument constructor, or one with arguments. So I understand the this() part of it which makes sense.

    And I'll just assume that after super() runs, it invokes the subclass constructor, which it must, otherwise there's no "another constructor" invoking it. Sorry to be so dense, but I really have tried to put some thought into this.

    As shown in the previous code snippet, your understanding of the execution order of the constructors is wrong! Its the subclass constructor which invokes the superclass constructor, and not the other way around.

    Mark Kevin wrote:I suppose whether its super() or this(), either of these is an "invocation from within a constructor."

    Exactly!

    Hope it helps!
    Kind regards,
    Roel
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Thank you! Much appreciated. Although I still don't understand which "other" or "another" constructor invokes the subclass constructor, which is how the text is written. But never mind. You've gone beyond the call and I'll sort it out later.

    I also don't quite understand how your statement ...

    main() invokes new C() => C() constructor is invoked


    ... is considered to be "invoking from another constructor" because it's from another method, not another constructor. I'm searching for an invocation of the subclass constructor (in the super() scenario) from "another constructor" (which is why I erroneously thought it might come from the superclass). It begs the question: "Which is the 'another constructor' from which supposedly the subclass constructor is invoked?" That seems to be the nub of the issue.

    Enough of this. I have over 1,000 more flash cards to wade through.

    Regards.

    m.

     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:I still don't understand which "other" or "another" constructor invokes the subclass constructor, which is how the text is written.

    To which text are you refering? The statement (bullet point) in the study guide or something I wrote in one of my previous posts? I assume it's something I wrote, because the bullet point in the study guide is "The only way a constructor can be invoked is from within another constructor." and thus it doesn't mention "subclass constructor". The first occurence about "subclass constructor" occurs in your post where you assume that the subclass constructor is invoked by the superclass constructor. That's wrong! As I tried to explain (but clearly didn't succeed) in my previous post: it's the subclass constructor which invokes the superclass constructor (using super() implicitly or explicitly)!

    Mark Kevin wrote:I also don't quite understand how your statement ...
    main() invokes new C() => C() constructor is invoked


    ... is considered to be "invoking from another constructor" because it's from another method, not another constructor.

    You are 100% correct about this one! That's indeed not an example of a constructor being invoked from another constructor, but that's just creating a new instance! I added this code snippet for two reasons: first illustrate the correct execution flow of parentclass and subclass constructors (because your understanding was wrong). Secondly illustrate the bullet point from the study guide ("The only way a constructor can be invoked is from within another constructor.") in abundance. The code snippet has four (4) examples of this statement
    Roel De Nijs wrote:
  • C() explicitly invokes C(int) => C(int) constructor is invoked
  • C(int) implicitly invokes super() => B() constructor is invoked
  • B() implicitly invokes super() => A() constructor is invoked
  • A() implicitly invokes super() => Object() constructor is invoked


  • Mark Kevin wrote:I'm searching for an invocation of the subclass constructor (in the super() scenario) from "another constructor" (which is why I erroneously thought it might come from the superclass). It begs the question: "Which is the 'another constructor' from which supposedly the subclass constructor is invoked?" That seems to be the nub of the issue.

    You have two ways to invoke another constructor: this() which invokes a constructor in the same class (e.g. in class C of the code snippet: this(5);); and super() which invokes a constructor in the parent class (e.g. classes A, B, and C of the code snippet all have implicit calls to super()). These are really the only two ways to invoke another constructor, so it's impossible to invoke a subclass constructor from the superclass constructor. That will never happen!
    As you (should) know, the compiler adds for you a call to super() to a constructor if you don't add an explicit call to this() or super() yourself. And the compiler will even add a default no-arg constructor (with call to super()) for you if you didn't explicitly provide a constructor for your class. So if we look at the three classes in the code snippet:
  • the compiler adds a call to super() to the A() constructor
  • the compiler adds a default no-arg constructor (with call to super()) to class B
  • the C() constructor already has an explicit call to another constructor using this(), so the compiler makes no changes
  • the compiler adds a call to super() to the C(int) constructor

  • So if we add all these changes in the existing code snippet, the code looks like this (added a few print statements as well to illustrate the execution flow of constructor invocation)Please note that this code snippet is 100% equivalent to the code snippet from my previous post. Running the TestABC class will result in this output:
    in A()
    in B()
    in C(int)
    in C()


    Mark Kevin wrote:I have over 1,000 more flash cards to wade through.

    Pfew, that's a whole lot. Happy studying!

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:
    Mark Kevin wrote:Any hints?

    Sure! Have a close look at the compiler error you get after compiling the Constructor class.

    Did you manage to find how you can make the Constructor class successfully compile with changing only one line? If not, here's another hint: can a method and a constructor have the same name?
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    I understand everything you are saying. But it still doesn't address the narrow issue I'm concerned about. Here is the quote from the text, the last bullet on page 129, that seems misleading:

    "The only way a constructor can be invoked is from within another constructor."

    Now, using the following code for reference, from within which constructor ("another constructor") is the constructor public B() invoked? There is none. There is an invocation from within the main() method, but that's not a constructor. And it obviously can't be invoked from within public A(), which you explained.

    Issue: From within which constructor is public B() invoked?
    I think I have a valid point.


     
    Sachin Tripathi
    Ranch Hand
    Posts: 368
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    That will be appropriately called as creating instance of specified class.
    While invoking the constructor is done basically from inside another constructor

    Do try to solve Roel's question, a lot of fun is waiting down there
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    All right, I think I solved your riddle. I changed the method name to Constructor() (I never would have thought of that), as both the constructor and method can have the same name, though I don't think that generally is a good idea. So it compiles (don't know why), but when I create an instance of Constructor and call the Constructor() method I get a slew of StackOverFlow errors because the method keeps calling itself. So just changing that one line, it seems, isn't effective from a practical point of view. I would have to do something else and change more than one line to make it run properly.

    Why does it compile?
    And why won't it invoke the constructor?

    Here is what I came up with:

     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:All right, I think I solved your riddle. I changed the method name to Constructor() (I never would have thought of that), as both the constructor and method can have the same name, though I don't think that generally is a good idea.

    You are absolutely spot-on! Although your wording is not 100% correct. You didn't actually change the method name to Constructor(). You turned the constructor Constructor() into a method (with the same name) by adding a return type. I never said it's considered to be a good practice to have a method name with the same name as your class (and thus the constructor as well) It was a nice bonus question which made you think and it illustrates that (although not recommended) you can have a constructor and method with exactly the same name and parameter list. The compiler is happy and doesn't complain (and thus no compiler errors), because it makes the difference based on the return type: a constructor doesn't have one and a method is required to have one.
    The updated code snippet (only void added to Constructor())The reason why this code snippet successfully compiles, is very simple (if you know ): as you know by now, you can't invoke a constructor in a method or (instance) initializer block by using only the name of the constructor (class). You must use the keyword new to create instances (using the constructor). But by adding void as a return type, Constructor() is not a constructor anymore (although its name suggests it still is), but it's a method! And you can invoke methods from within methods or (instance) initializer blocks.

    Mark Kevin wrote:So it compiles (don't know why), but when I create an instance of Constructor and call the Constructor() method I get a slew of StackOverFlow errors because the method keeps calling itself. So just changing that one line, it seems, isn't effective from a practical point of view. I would have to do something else and change more than one line to make it run properly.

    The reason why the code compiles, I just have explained. If you still have doubts after this explanation, just let us know. And about the StackOverflowError you are absolutely correct because in your code snippet the method Constructor() simply invokes itself recursively. So if a method is recursively invoked without any exit condition, a StackOverflowError will be thrown at a given moment. The most easy fix is to change the method name (like in my code snippet, the name of the method invoking Constructor() is create). So this code snippet runs fineOutput:
    in Constructor
    in Constructor


    Another possibility is to add some kind of exit condition to end the recursive calls at some point. For example, this code snippet will recursively invoke Constructor() 3 times and then the exit condition is met and no further invocations will happen (and thus preventing the StackOverflowError)Output:
    in Constructor: 1
    in Constructor: 2
    in Constructor: 3
    in Constructor: 1
    in Constructor: 2
    in Constructor: 3


    Mark Kevin wrote:And why won't it invoke the constructor?

    Because there's a difference between the constructor and a method: a constructor doesn't have a return type and outside a constructor it can only be invoked using new (to create new instances of the class); a method must have a return type and when you invoke a method you don't use new (because that's solely reserved to create new instances).

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:Now, using the following code for reference, from within which constructor ("another constructor") is the constructor public B() invoked? There is none. There is an invocation from within the main() method, but that's not a constructor. And it obviously can't be invoked from within public A(), which you explained.

    Issue: From within which constructor is public B() invoked?
    I think I have a valid point.

    Ok, now I see what you meant, sometimes adding a code snippet can be crystal-clear In this code snippet there's indeed no other constructor which will invoke B(). But that's not a violation of the bullet point in the study guide: "The only way a constructor can be invoked is from within another constructor". It says that you can only invoke a constructor from within another constructor. It doesn't say that every constructor must be invoked from within another constructor.

    If a new B(int) constructor is added, like in this code snippetthe B() constructor is invoked from within another constructor, but the B(int) constructor is not. But as previously stated, it's not a requirement that any constructor is invoked from within another constructor.

    Hope it helps!
    Kind regards,
    Roel
     
    Paul Anilprem
    Enthuware Software Support
    Ranch Hand
    Posts: 3820
    10
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I think the statement, "The only way a constructor can be invoked is from within another constructor" is ambiguous because it doesn't make a distinction between "invoked" directly by the programmer (as in calling a method) and "invoked" indirectly as a result of programmer doing something else i.e. creating a new instance.

    IMHO, the verb "invoke" has connotations of some form of indirection as opposed to verb "call", which signifies a direct action.

     
    Sachin Tripathi
    Ranch Hand
    Posts: 368
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:Ok, now I see what you meant, sometimes adding a code snippet can be crystal-clear In this code snippet there's indeed no other constructor which will invoke B(). But that's not a violation of the bullet point in the study guide: "The only way a constructor can be invoked is from within another constructor". It says that you can only invoke a constructor from within another constructor. It doesn't say that every constructor must be invoked from within another constructor.



    Seriously this is the first time,Roel when you don't make much sense,as far as I think

    Using "way" in the textbook, they clearly want to emphasis, that the only way a constructor can be invoked is only through another constructor

    What you are saying is about the number of constructor that can be invoked from another constructor, i. e. 1
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    The reason why the code compiles, I just have explained. If you still have doubts after this explanation, just let us know. And about the StackOverflowError you are absolutely correct because in your code snippet the method Constructor() simply invokes itself recursively. So if a method is recursively invoked without any exit condition, a StackOverflowError will be thrown at a given moment. The most easy fix is to change the method name (like in my code snippet, the name of the method invoking Constructor() is create). So this code snippet runs fine





    So even though my change allowed it to compile I had it all wrong. I changed create() to Constructor(), but what I should have done is simply added a return type, void, to the constructor Constructor and turned it into a method. Then, using "new" I can create an object with Constructor c = new Constructor();

    It reminds me of Joshua Bloch's first item: Consider static factory methods instead of constructors. ... except here it's not static.

    Can you clarify something for me? Which line creates the object?


    So this line is now calling a method instead of a constructor? It creates an instance of the Constructor class by calling a regular method, the magic word being 'new'?





     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Using "way" in the textbook, they clearly want to emphasis, that the only way a constructor can be invoked is only through another constructor


    Thank you, Sachin.

    That bullet needs to be reworded because it is incorrect on its face and states that invoking a constructor from within main() is illegal, which it is not.

    Mark
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Issue: From within which constructor is public B() invoked?


    What specific line of code invokes B()? From within which constructor ("another constructor")?

    Not trying to be difficult. Trying to be accurate.



     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sachin Tripathi wrote:Using "way" in the textbook, they clearly want to emphasis, that the only way a constructor can be invoked is only through another constructor

    What you are saying is about the number of constructor that can be invoked from another constructor, i. e. 1

    Maybe that's some misinterpretation on your side or maybe not being clear at my side. But although you are correct (from each constructor exactly one other constructor is invoked), it's not what I intended to explain/clarify. The one and only thing this statement ("The only way a constructor can be invoked is from within another constructor") is trying to explain is: you can only invoke a constructor from within another constructor. You can't invoke a constructor from a method, a (static) initializer block, and so on.

    I think you should make a clear distinction between invoking constructors and creating objects. The first one can only be done from within another constructor (using this() or super()). The latter one is done by invoking/calling the new keyword followed by a call to a constructor. And that's of course not the same as "invoking a constructor".

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:That bullet needs to be reworded because it is incorrect on its face and states that invoking a constructor from within main() is illegal, which it is not.

    And what would you consider to be a better rewording for that statement? The only possible improvement I can think of, would be: "The only way a constructor can be invoked is from within another constructor (using this() or super() as the first statement)."

    Because invoking a constructor from within main() or any other method is illegal and thus results in a compiler error (as already mentioned in earlier posts).Don't forget there's a difference between invoking a constructor and creating objects. The first one can only be done from within another constructor (using this() or super()). The latter one is done by invoking/calling the new keyword followed by a call to a constructor (e.g. new ClassX();). And that's of course not the same as "invoking a constructor". This code snippet compiles successfully and creates one object/instance

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:So even though my change allowed it to compile I had it all wrong. I changed create() to Constructor(), but what I should have done is simply added a return type, void, to the constructor Constructor and turned it into a method. Then, using "new" I can create an object with Constructor c = new Constructor();

    Exactly! You could of course have made many changes to the code snippet, but the one that makes the difference is adding a return type to constructor Constructor() which makes it no longer a constructor but a method. Because a method must have a return type and can have the same name as the class (although not recommended); whereas a constructor must not have a return type and must have the same name as the class.

    Mark Kevin wrote:Can you clarify something for me? Which line creates the object?

    Line D (Constructor c = new Constructor();) is creating the new object and assign it to reference variable c.

    Mark Kevin wrote:So this line is now calling a method instead of a constructor? It creates an instance of the Constructor class by calling a regular method, the magic word being 'new'?

    No, definitely not! To create a new object/instance you always need a constructor, you can never create a new object/instance by calling a method. Repeat after me: to create a new object/instance you always need a constructor! So Line D actually invokes a constructor of the Constructor class. In fact, it invokes the default no-arg constructor. But where is that constructor? Because you didn't define a constructor yourself (remember you turned the only constructor Constructor() into a method by adding a return type), the compiler will add a default constructor for you: the default constructor is always a no-arg constructor with a call to super(). So that's kind of a convenience for the developers: if you don't provide a constructor, the compiler adds one for you. So you don't have to bother about adding this boilerplate code and still every class is guaranteed to have (at least) one constructor (thanks to the compiler's work).
    So after the compiler has compiled your Constructor class, it looks like this (removed all comment lines)

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:
    Issue: From within which constructor is public B() invoked?


    What specific line of code invokes B()? From within which constructor ("another constructor")?

    Not trying to be difficult. Trying to be accurate.

    In short: the constructor B() is not invoked from within another constructor. In this (previous) post, I already tried to give an in-depth explanation about that code snippet.
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You said,
    The latter one is done by invoking/calling the new keyword followed by a call to a constructor. And that's of course not the same as "invoking a constructor".


    But not according to what you wrote earlier when referring to a different snippet, which was:

    main() invokes new C() => C() constructor is invoked


    According to your earlier statement it does indeed invoke the constructor, even though it's not within another constructor. But even if you are correct, it still doesn't answer the question. Where is the code that invokes the constructor B() if it's not within main()?

    You explained a lot, but are unable to point to that one statement, that one line of code, which invokes the constructor B(); that invoking statement must be within "another constructor".

    I believe, and I candidly admit I'm no Java expert, but I think the last bullet on page 129 should be reworded as follows (or something similar), and I think the authors would agree if they thought about it some more:

    "The only way a constructor can be invoked is from within another constructor (using a call to super() or this()), or from within a method with the call to the constructor preceded by the keyword 'new'."

    Where is that one statement outside of main(), that line of code, within another constructor, that invokes B()? There is none. It's impossible.

    But enough of this. ...



    It has to be invoked from somewhere, doesn't it? If not from within main() with the keyword new, where?


     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You wrote:

    In short: the constructor B() is not invoked from within another constructor.


    Exactly!! You just proved my point. It's invoked from within main() using the keyword new preceding the call to the constructor Constructor(), (or new B()).

    In fact, the first bullet on page 152 says, "A constructor is always invoked when a new object is created." Which settles the issue for me.

    We can debate if that line in main() is called an invocation; after all, we invoke methods all the time. They taught me so in class. And a constructor is technically a constructor method, so a broader definition of "invoke" is entirely proper. And if the authors intend "invoke" to be interpreted very narrowly and not apply to methods like main(), then we are back to square one and they need to rewrite the first bullet on page 152. Where is the line of code that invokes it? There is only one possible answer it seems, in main(). The call to the constructor method B() invokes the constructor, and 'new' "dynamically allocates memory for [that] object" according to Schildt p. 113. If it doesn't, then we have a problem.

    Therefore, an invocation to a constructor does not always have to come from within another constructor, but can also come from within a method if the call is preceded by the keyword 'new.'

    The only way I can create an instance of subclass B() is if I use a constructor.




     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:I believe, and I candidly admit I'm no Java expert, but I think the last bullet on page 129 should be reworded as follows (or something similar), and I think the authors would agree if they thought about it some more:

    "The only way a constructor can be invoked is from within another constructor (using a call to super() or this()), or from within a method with the call to the constructor preceded by the keyword 'new'."

    First of all, from my experience authors are unlikely to change a statement which is not an obvious mistake but more an interpretation issue. And they definitely don't do it, if this issue is reported only once (or twice). And as far as I can remember, you are the only one who mentioned this possible issue (or at least took the effort to mention it).
    Secondly your suggestion is also incorrect, because if you invoke the new operator followed by a call to the constructor, you can do it from anywhere (static and instance methods, static and instance initializer blocks and even constructors as well), it's not limited to methods only.
     
    Sachin Tripathi
    Ranch Hand
    Posts: 368
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:
    Maybe that's some misinterpretation on your side or maybe not being clear at my side. But although you are correct (from each constructor exactly one other constructor is invoked), it's not what I intended to explain/clarify.


    I added one more bullet point..
     
    Sachin Tripathi
    Ranch Hand
    Posts: 368
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:"The only way a constructor can be invoked is from within another constructor (using this() or super() as the first statement)."

    That surely improves the bullet point(make it more clear),and @Mark:No one argues with Roel here
    He is a king,and this forum is his kings Landing(Believe me ,he never makes mistake)

    if you consider how you invoke a method,you will understand whatever he(and K&B) are saying is absolutely right



     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sachin Tripathi wrote:
    Roel De Nijs wrote:
    Maybe that's some misinterpretation on your side or maybe not being clear at my side. But although you are correct (from each constructor exactly one other constructor is invoked), it's not what I intended to explain/clarify.


    I added one more bullet point..

    That's already a logical consequence and implication from the second bullet point on page 129
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sachin Tripathi wrote:That surely improves the bullet point(make it more clear),and @Mark:No one argues with Roel here
    He is a king,and this forum is his kings Landing(Believe me ,he never makes mistake)

    I don't want to be a king at all (that's why most of my posts end with "Roel" and not with "King" ) And I definitely not want to create a situation where no one dares to argue or start a discussion because your opinion is different from mine. As a developer (and a person as well), you should always be critical. That's really a good quality (but being critical is not the same as being stubborn ).
    My main goal and objective in this forum which I try to fulfill to the best of my abilities: explain as clear as possible the doubts other ranchers have and answer questions as detailed as possible, trying my best to make no mistakes when doing so. Because these exam topics are already hard to understand and even a little mistake might add confusion or provide incorrect information, which is a bad thing if you are learning/studying new concepts/topics.

    If you have a different opinion, don't be afraid and just share them! An enlightening discussion can also be very instructive. Certainly if it's about basic concepts. Because my opinion might be of course (a little) biased, because I have several years of experience In Java (and read certification study guides many times). So for me a statement can be crystal-clear, but for someone who is new to the Java programming language it might be hard to understand or even confusing. Sharing your doubts and confusion and having a great discussion about them (like Mark did in this thread) will probably help you to clear them in the end and results in a much better understanding of some concepts.
     
    Sachin Tripathi
    Ranch Hand
    Posts: 368
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    My post was meant to lighten up things...(Nothing serious)
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Let's have a look at the full statement again:
    K&B7, page 129 wrote:The only way a constructor can be invoked is from within another constructor.
    In other words, you can't write code that actually calls a constructor as follows:

    So based upon the code snippet, it seems this bullet point is just about the illegality of calling the constructor using its name without the new operator. And that's always illegal, even from within a constructorSo maybe it would make more sense and be more obvious to rephrase the first sentence of that bullet point to something like: "Trying to invoke a constructor like you would invoke a method (using only its name) is not allowed". What do you think? Suggestions?

    Hope it helps!
    Kind regards,
    Roel
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator


    Secondly your suggestion is also incorrect, because if you invoke the new operator followed by a call to the constructor, you can do it from anywhere (static and instance methods, static and instance initializer blocks and even constructors as well), it's not limited to methods only.


    My suggestion is not incorrect; it just needs to be supplemented with your suggestions to be more accurate, including the following:

    Trying to invoke a constructor like you would invoke a method (using only its name) is not allowed.



    So all you need to do is expand what I wrote as follows:

    "The only way a constructor can be invoked is from within another constructor (using a call to super() or this()), or from within static or instance methods, static or instance initializer blocks, or even constructors, if the call to the constructor is preceded by the keyword 'new'." Trying to invoke a constructor like you would invoke a method (using only its name) is not allowed."

    The original bullet, "The only way a constructor can be invoked is from within another constructor," while well-meaning, is false.



     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Don't forget there's a difference between invoking a constructor and creating objects. The first one can only be done from within another constructor (using this() or super()). The latter one is done by invoking/calling the new keyword followed by a call to a constructor (e.g. new ClassX();). And that's of course not the same as "invoking a constructor".


    That's not correct. The first bullet on page 152 proves it. "A constructor is always invoked when a new object is created." You're splitting non-existent hairs. When you create an object you invoke a constructor in these circumstances; they are inseparable.
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mark Kevin wrote:My suggestion is not incorrect;

    The suggestion you made was incomplete and thus incorrect.

    Mark Kevin wrote:"The only way a constructor can be invoked is from within another constructor (using a call to super() or this()), or from within static or instance methods, static or instance initializer blocks, or even constructors, if the call to the constructor is preceded by the keyword 'new'." Trying to invoke a constructor like you would invoke a method (using only its name) is not allowed."

    Although that's a good attempt, I don't think it fits well for a bullet list notation where statements are mostly concise and to the point. And if that's the first sentence, the second sentence (of the original bullet point) and the code snippet would make very little or no sense at all (as it focuses on one very particular part of the whole statement).
     
    Mark Kevin
    Ranch Hand
    Posts: 44
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator


    The suggestion you made was incomplete and thus incorrect.


    False logic. Incomplete is not necessarily incorrect. That would be like saying a person is from Brussels, but because you didn't mention he was also from Belgium he's not from Belgium.
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic