I'm getting confused about when the instance initialization block should run.
According to Kathy Sierra's book:
Instance init blocks run every time a class instance is created
So, consider having two classes: a parent and a child, according to this question and java's documentation:
instantiating a subclass object creates only 1 object of the subclass
type, but invokes the constructors of all of its superclasses.
According to the above:
why does the instance initialization block located in superclasses gets called every time an object of the subclass is instantiated? it isn't like that a new object of the superclass is instantiated.
After compilation instance init blocks become part of constructors. javac simply adds the init block to each constructor, that is this:
public class Test1 {
int x;
int y;
{
x = 1;
}
Test1() {
y = 1;
}
}
Is equivalent to this:
public class Test1 {
int x;
int y;
Test1() {
x = 1;
y = 1;
}
}
So the init block runs when constructor runs.
it isn't like that a new object of the superclass is instantiated.
Actually, it is like that.
Every instance of a subclass implicitly contains an instance of its superclass.
A superclass constructor is always invoked as the first step in any constructor (and that in turn runs any instance initializer blocks for the superclass)
Though it was a old post I came across this concept thought worth sharing it
Since we are talking about instance block here is how instance code flow executes in parent child relation class
// Child extends Parent
If we create a object for Child
1) Identification of instance members of the class from parent to child
2) execution of instance variable assignments and instance blocks only on parent class
3)execution of parent constructor
4)execution of instance variable assignments and instance blocks only on Child class
5)Execution of child constructor
Because there is always an implicit super() call(if not done explicitly) to the parent's constructor in the constructor of the child.
Related
This question already has answers here:
Difference between "this" and"super" keywords in Java
(9 answers)
Closed 4 years ago.
I am trying to find proof for the statement - keyword super is the reference to parent class just like keyword this is the reference to current class.
I am trying multilevel Inheritance in Java A->B->C: class A is grand parent, class B is parent, class C is child.
I have a variable X declared in all three classes with values respectively (A:x=100,B:x=200,C:x=300)
In the child class constructor I am printing values. However the casting isn't working for super keyword whereas it's working for this keyword.
((A)super).x is not working, but ((A)this).x is working.
class A {
int x = 100;
}
class B extends A {
int x = 200;
}
public class C extends B {
int x = 300;
public C () {
System.out.println(this.x); //OP = 300
System.out.println(super.x); // OP = 200
System.out.println(((A)this).x);// OP = 100
System.out.println(((A)super).x); // Giving Compile time Error.. Why?
B reftoB = new B();
System.out.println(((A)reftoB).x); // OP = 100
}
public static void main(String[] args) {
C t1= new C();
}
}
I expect the output of System.out.println(((A)super).x) is 100, but it is giving a compile time error.
So my question is if super is a reference to the parent class then why isn't type casting working on it?
Use of Super Keyword:
super() can be used to refer immediate parent class instance
variable.
super() can be used to invoke immediate parent class method.
super() can be used to invoke immediate parent class constructor.
Your compiler is a compilation error for (A)super).x , because it is not a valid statement, moreover we don't use it this way, ontop of all It violates encapsulation, you should not able to bypass parent class. In every definition of super() you will find something mentioned as current parent class, but what you are trying to do here is bypassing current parent.
Now coming to your problem:
x // Field x in class C
this.x // Field x in class C
super.x // Field x in class B
((B)this).x // Field x in class B
((A)this).x // Field x in class A
super.super.x // Illegal; does not refer to x in class A
((A)super).x // Illegal as well as compilation error
If you still want to access variables like what you intented then use something like below:
t1.x // Field x of class C
((B)t1).x // Field x of class B
((A)t1).x // Field x of class A
Note: t1 is your class C instance.
The answer to why this can be cast but super cannot is the same answer to the question why this can be passed as a method argument but super cannot: namely, because this is defined by the JLS as a Primary Expression but super is not.
The super keyword refers to a class parent, and this keyword refers to the class you are in. Let's create a parent class to start the demonstration:
public class ParentClass{
private int justANumber;
public ParentClass(int justANumber){
this.justANumber = justANumber;
}
}
Notice how the this keyword is used here, which is telling "Hey, assign the justANumber value to THIS class attribute also called justANumber". Let's create a subclass for this parent class now:
public class Subclass extends ParentClass{
// You don't need to declare the justANumber variable, cause it's from the parent
public Subclass(int justANumber){
super(justANumber);
}
public showNumber(){
return this.justANumber;
}
}
The super() method calls the parent constructor, which need an int value on the first place, so you pass it as an argument. Now see how the showNumber() method returns this.justANumber? Why? that's because when the super() method is called, the parent class automatically delegates his variables to the subclass, so in this case, Subclass can now say that justANumber is HIS variable, being able to use the this keyword. Hope you now understand de difference.
Hopefully this question hasn't already been asked. I've had a look around but haven't found a similar post.
Experimenting in Java I've noticed that there is no restriction on having duplicate method signatures in a nested class, which seems counter-intuitive.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
}
}
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
Edit: I appreciate that the core of the question is the same as this post, however, I was more interested in understanding why this behaviour is allowed as it wasn't immediately clear to me.
Where a class is defined doesn't matter so much. Keep in mind, in the end you have
class A { int x()
and
class A.B { int x()
Two (almost) independent classes. The only relationship that we have here is that any instance of B needs an "enclosing" instance of A to which it belongs (because it is a non-static inner class).
And of course, you can access the "enclosing" A "stuff" from within B, for example using A.this.x().
This should be available somewhere in the JLS - but ultimately it boils down to scope. Each of them has a different scope - thus the compiler does not complain.
Why would the compiler complain? They are two different classes, they just happen to be nested.
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
A.this.x()
At first method signature is not the combination of return type and method name it is method name and parameters.
if you call x() it will run x() inside the B
A.this.x(); it will run x() in A
Its scope, it's similar to have an instance variable called foo and then a local one in the method called foo as well.
Its worth reading about scope in java
Inner class in java can access all the members (i.e variables and methods) including private one, but outer class can not access member of inner class directly.
To access x() method of class B inside class A you can either create B's instance and call it or call like this A.this.x();
To access x() method outside class A you can do something like this:
B b = a.new B();
b.x();
If you are using non-static nested class (inner class) then it wouldn't be able to access to x method of B class from other classes. But if you are using static nested class you will be able to access that method from other classes. Example:
public class A {
int x() {
new A.B().x();
return 1;
}
static class B {
int x() {
new A().x();
return 2;
}
}
}
public static void main(String[] args) {
A a = new A();
a.x();
B b = new A.B();
b.x();
}
I hope this example answering your question... ☺
B is nested inside A. According to scope rules we can do the following:
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
int xOfA(){
return A.this.x();
}
}
public static void main(String[] args) {
final A objA = new A();
final B objB = objA.new B();
System.out.println(objA.x());
System.out.println(objB.x());
System.out.println(objB.xOfA());
}
}
that is because B is visible from an instance of A.
Moreover B can reference methods in the containing class through their full paths.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
When you define something in a nest scope which is otherwise in an outer scope, this is hiding.
What is important is that -: The version of a method that is executed will NOT be determined by the object that is used to invoke it. In fact it will be determined by the type of reference variable used to invoke the method
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
So as it is clear from above we can access it using class name, eg A.x
Hope this helps!!
How to call the Constructor multiple times using the same object
class a
{
a(int i)
{
System.out.println(i);
}
public static void main(String args[])
{
a b = new a();
int x = 10;
while( x > 0)
{
//Needed to pass the x value to constructor muliple times
}
}
}
I needed to pass the parameter to that constructor.
Constructor of a class A constructs the objects of class A.
Construction of an object happens only once, and after that you can modify the state of the object using methods (functions).
Also notice if programmer does not write any constructor in his class then the Java compiler puts the constructor for the class (public constructor without any parameters) on its own.
In the case where a constructor has been provided by the programmer, the compiler does not create a default constructor. It assumes, the programmer knows and wants creation of the objects of his/her class as per the signature of the explicit constructor.
Constructor calls are chained. Suppose there exists below class relationship.
Child.java extends Parent.java and Parent.java extends GrandParent.java.
Now if Child child = new Child(); is done, only one object is created and that is of Child.java, but the object also has all of the features of GrandParent first then with the features of the Parent and then the Child.
Hence first constructor of GrandParent.java is called then Parent.java is called and lastly the constructor of Child.java is called.
Constructors are special and different from other methods.
The intent of constructors is to create the object, so each time you use the new operator, the constructor is called and a new object is created. You can not call the constructor directly. You need the new operator to call it. Even if you see some class defining methods like getInstance(), it still uses the new operator to construct the object and return the created object.
*PS there are ways to create an object without calling constructor (like Serialization) but that is out of context of the discussion here.
Constructors are called only once at the time of the creation of the object.
Can you please be specific about what you want to achieve?
But I think you could try one of the following two things.
Calling the constructor to create a new object and assigning it to the object 'b':
b = new a(1);
Using the setter method:
void setI(int i){
this.i = i;
}
b.setI(1);
int x = 10;
while( x > 0)
{
a b = new a(x);
}
I have just started learning Java.I understand
Unlike instance method, instance variable can not be overridden, and are not dynamically picked by JVM at run time when accessed polymorphically.
flow of execution : static block, super constructor, initialization block and then constructor.
But I am stuck at one code, where I have polymorphically invoked a instance variable but its showing overridden value (which it should not show). The instance variable is overridden inside sub class' init block.
package package1;
public class Other {
public static void main(String [] args){
Parent referToChild = new Child();
Parent referToChildTwo = new ChildTwo();
System.out.println("age as referred by referToChild reference variable is:" + referToChild.age);// prints 35 (doubt 1)
System.out.println("age as referred by referToChildTwo reference variable is:" + referToChildTwo.age);// prints 50 (doubt 2)
System.out.println("money as referred by Other reference variable is:" + referToChild.money);
//System.out.println("Other reference variable is:" + othObj.age);
}
}
class Child extends Parent{
// init block
{
age = 35;
}
}
class ChildTwo extends Parent{
public int age;
{
age = 40;
}
}
class Parent{
public int age = 50;
public int money = 100;
}
The answer I get is:
35
50
100
so my doubts are:
doubt 1 :Why is it showing "35", it should display super class' variable's value which is 50.
doubt 2 : When it is displaying sub class' variable's value for last case, then why not for this case.
Why is it showing "35", it should display super class' variable's value which is 50.
The initializer block of subclass Child executes after the variable age is initialized in the Parent class. Therefore, age is first initialized to 50, then to 35.
This is explained in great detail in the Java Language Specification Section 12.5 on Creation of New Class Instances, with the relevant part in bold:
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
As for the second question, referToChildTwo is declared of type Parent, while its actual type is ChildTwo. A ChildTwo instance has two age fields, the one defined in ChildTwo and the other one inherited from Parent.
When you write the expression referToChildTwo.age, the field inherited in Parent will be evaluated. To evaluate the one defined in the subclass, you would need to cast the variable, i.e. ((ChildTwo)referToChildTwo).age.
It cannot be overridden, but it is inherited by child classes as long as it wasn't private in the parent. And they can access it, including both reading and writing it.
Overriding is creating a new member which is part of the current class, which has the same definition of the member of the parent class, and for that member to be accessed when you use the object polymorphically.
For example:
class Parent {
public int age = 50;
}
class Child {
public int age = 80;
}
Here we defined a new member, age, which is separate from the parent's age. If you access it from inside Child using this.age, you'll get 80. If you access the parent's age using super.age, you'll get 50.
But this is not overriding, because if you use the object polymorphically, it will access the parent's age:
Child childObj = new Child();
Parent parentObj = childObj;
System.out.println( childObj.age ); // Will print 80
System.out.println( parentObj.age ); // Will print 50
This is despite the fact that they are both the same object. That's because the child hides the field rather than override it.
Simply assigning a value in a field inherited from the parent is not overriding. It's part of what inheritance is all about.
Consider the int a variables in these classes:
class Foo {
public int a = 3;
public void addFive() { a += 5; System.out.print("f "); }
}
class Bar extends Foo {
public int a = 8;
public void addFive() { this.a += 5; System.out.print("b " ); }
}
public class test {
public static void main(String [] args){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I understand that the method addFive() have been overridden in the child class, and in class test when the base class reference referring to child class is used to call the overridden method, the child class version of addFive is called.
But what about the public instance variable a? What happens when both base class and derived class have the same variable?
The output of the above program is
b 3
How does this happen?
There are actually two distinct public instance variables called a.
A Foo object has a Foo.a variable.
A Bar object has both Foo.a and Bar.a variables.
When you run this:
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
the addFive method is updating the Bar.a variable, and then reading the Foo.a variable. To read the Bar.a variable, you would need to do this:
System.out.println(((Bar) f).a);
The technical term for what is happening here is "hiding". Refer to the JLS section 8.3, and section 8.3.3.2 for an example.
Note that hiding also applies to static methods with the same signature.
However instance methods with the same signature are "overridden" not "hidden", and you cannot access the version of a method that is overridden from the outside. (Within the class that overrides a method, the overridden method can be called using super. However, that's the only situation where this is allowed. The reason that accessing overridden methods is generally forbidden is that it would break data abstraction.)
The recommended way to avoid the confusion of (accidental) hiding is to declare your instance variables as private and access them via getter and setter methods. There are lots of other good reasons for using getters and setters too.
It should also be noted that: 1) Exposing public variables (like a) is generally a bad idea, because it leads to weak abstraction, unwanted coupling, and other problems. 2) Intentionally declaring a 2nd public a variable in the child class is a truly awful idea.
From JLS
8.3.3.2 Example: Hiding of Instance Variables This example is similar to
that in the previous section, but uses
instance variables rather than static
variables. The code:
class Point {
int x = 2;
}
class Test extends Point {
double x = 4.7;
void printBoth() {
System.out.println(x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
sample.printBoth();
System.out.println(sample.x + " " +
((Point)sample).x);
}
}
produces the output:
4.7 2
4.7 2
because the declaration of x in class
Test hides the definition of x in
class Point, so class Test does not
inherit the field x from its
superclass Point. It must be noted,
however, that while the field x of
class Point is not inherited by class
Test, it is nevertheless implemented
by instances of class Test. In other
words, every instance of class Test
contains two fields, one of type int
and one of type double. Both fields
bear the name x, but within the
declaration of class Test, the simple
name x always refers to the field
declared within class Test. Code in
instance methods of class Test may
refer to the instance variable x of
class Point as super.x.
Code that uses a field access
expression to access field x will
access the field named x in the class
indicated by the type of reference
expression. Thus, the expression
sample.x accesses a double value, the
instance variable declared in class
Test, because the type of the variable
sample is Test, but the expression
((Point)sample).x accesses an int
value, the instance variable declared
in class Point, because of the cast to
type Point.
In inheritance, a Base class object can refer to an instance of Derived class.
So this is how Foo f = new Bar(); works okay.
Now when f.addFive(); statement gets invoked it actually calls the 'addFive() method of the Derived class instance using the reference variable of the Base class. So ultimately the method of 'Bar' class gets invoked. But as you see the addFive() method of 'Bar' class just prints 'b ' and not the value of 'a'.
The next statement i.e. System.out.println(f.a) is the one that actually prints the value of a which ultimately gets appended to the previous output and so you see the final output as 'b 3'. Here the value of a used is that of 'Foo' class.
Hope this trick execution & coding is clear and you understood how you got the output as 'b 3'.
Here F is of type Foo and f variable is holding Bar object but java runtime gets the f.a from the class Foo.This is because in Java variable names are resolved using the reference type and not the object which it is referring.