• Post Reply Bookmark Topic Watch Topic
  • New Topic

Difference between with class variable initialized or not initialized.  RSS feed

 
Tomasz Wolak
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So here are two essentially identical classes (note difference line 5)

and

Here is the tester:

here is the outcome:

Note the difference (line5): Child initialized the "X" variable to "null" while the Child2 didn't.
This seems a bit odd behaviour to me? I don't understand why this would take place. Your explanation i appreciated. I am using java (build 1.6.0_23-b05).
Thanks for input!
Tomek
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think we have enough information.

The constructors of Child and Child2 both invoke the constructor of their superclass, Parent, and you don't show the source for that.

Child2 has a syntax error, so it isn't really the code you're using. Line 5, you see, has "private String;", but Java requires that you put a variable after that.

So give us the real Child2 source and the parent source, and anything else that is not as shown here.

rc
 
Tomasz Wolak
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry about that! And yes you are right, I missed the variable name. So much for fast edits!
here it the super class:
 
Matt Hanrahan
Greenhorn
Posts: 14
Netscape
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is this from a book or tutorial? It seems like an interesting problem.
Are are the public and privates marked correctly?

It seems to be an exercise on encapsulation or constructors or both.

Sorry wish I had an answer.

-Matt
 
Tomasz Wolak
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've just run at this today at work.
I watched this in debugger and I know what it is doing. I just don't understand why.
When the constructor to the super is invoked it first goes to implemented setInit() method.
The method in the child is invoked and the 'x' attribute is set (in both implementation of child).
The super.constructor regains control and now it get's interesting: the class that is initiated with "null" is reset to null even though it was set by the setInit() method.
I would expect the constructor in Parent not reset the value to "null" if it was already initiated by child class. OR I would expect both cases to behave in the same way.
I modified this bit more to illustrate what is doing. This time I only have one implementation of the child to make things easier to follow. The child class has two attributes one initialized to 'null' the other not at all:

You can clearly see that both attributes are set. But somehow the constructor re-initiates the already set attributes IF the attributes are initiated in the class declaration to begin with.

This sort of feels like a bug to me.
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16057
88
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First, something about inheritance. In Java (and most other object oriented programming languages), inheritance means specialization: a subclass is a specialized form of its superclass. For example, if you have a superclass Animal and a subclass Dog, then you can see this clearly: a Dog is a specific kind of Animal.

Using names such as "Parent" and "Child" for superclasses and subclasses confuses the biological meaning of the word "inheritance" with the meaning that it has in object oriented programming. Note that if you make a superclass Parent and a subclass Child, what you're expressing is that a Child is a specific kind of Parent. In biological terms, that doesn't make sense. To avoid confusion, it's better to not use names such as "Parent" and "Child" for superclasses and subclasses.

An object of a subclass type, for example a Dog, consists of a superclass part (the member variables that are in class Animal) and a subclass part (the member variables in class Dog). When you create a new Dog object, the superclass part will be initialized first. So, first the constructor of class Animal will run. After that, the subclass part will be initialized, and the constructor of class Dog will run. Not only the constructors will be run in that order, but also the member variables will be initialized in that order: first, member variables of Animal are initialized, then the Animal constructor will run, then member variables of Dog are initialized, and the Dog constructor will run.

Now, look at what's happening in your example:

First, the Parent constructor will run. This calls a setInit method that's overridden in the Child class. The setInit method sets the values of x and y in the Child class.
Then, the member variables in class Child will be initialized. In line 3 of class Child you've provided an explicit initialization value for x, so x will be initialized to that (null).
Note that the values that you've set by calling the setInit method in the constructor of Parent are now wiped out!
Then, the Child constructor will run. You'll see that x has been set to null there.

Note that you are actually calling the setInit method in class Child before the Child part is initialized. That can be dangerous (the Child part is in an uninitialized state at that moment!). Because of that, and because of the surprising way this works to most people, it's better to not call any non-final methods (methods that may have been overridden) in the same class from a constructor. I think that static code checking tools such as FindBugs would warn you if you had this construction in your code.
 
Tomasz Wolak
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks. This is indeed what I have suspected. This is not to say that I think it makes sense makes logical sense but that's another discussion.

So here is follow up question: other than starting off with uninitialized variables to begin with, is there something else that will allow subclass to set up variables when called upon from the constructor of the superclass without fearing that it'll be wiped out?
Thanks
Tomek
 
Matt Hanrahan
Greenhorn
Posts: 14
Netscape
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tomek,

Thanks for a very interesting topic.

Jesper,

Thank you for the detailed explanation.
I'm sensing this has something to do with object creation reference variables and the stack and the heap, but I'll leave the real answer to Jesper if he has time.

Thanks again all, I find this very engaging.

-Matt
 
Jean John
Greenhorn
Posts: 24
Android Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jesper/All,
Isn't this simply because the explicit initialization for the child class happens when the constructor of child class actually starts. ie.after super(). And then the initializations within the subclass constructors(if any) happen. So if you have given an explicit initialization, that value gets assigned to your instance variable when the subclass is initialized after superclass initialization. If you don't have any explicit initialization, the value that was set by the overridden subclass function setInit() remains. Hence child2 retains Hello, and child has null for the instance variable x.

Regards,
Jean
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!