I have this code:
public class Parent
{
int num;
Parent p;
Parent()
{
}
Parent(Parent s)
{
p=s;
}
void Print()
{
System.out.println(p.num);
}
}
and:
public class Child
{
public static void main(String args[])
{
Parent p1=new Parent();
Parent p2=new Parent(p1);
Parent p3=new Parent(p2);
p2.num=5;//line 1
p2.Print();//Line 2
}
}
The O/p is 0. This is true when I replace the Line 1 and 2 with p3.num=5 and p3.Print() respectively. But when I replace it with p1.num=5 and p1.Print(), I get a Runtime error (NullPointerException). Can anyone explain this behavior?
p1 is instantiated with the parameter-less constructor, which doesn't initialize the p member. Therefore, calling Print on that instance causes NullPointerException when you try to access the num member for a null reference - p.num.
BTW, the Child class is completely useless in this example. It doesn't extend Parent class, and you are not instantiating it anyway. The same code would have behaved the same if you moved the main method to the Parent class.
That is a very strange class. The Print method of an instance prints the num associated with the p passed into the constructor. You have two constructors, one of which doesn't ever set p, which means p will be null if you use that constructor; your other constructor remembers the Parent you give it by assigning it to p.
So:
Calling p1.Print() will fail because p1's p is null, so trying to use p.num throws an NPE.
Calling p2.Print() will show p1's num, which is 0 because you never set it to anything and the default value for data members is the "all zeroes" value, so 0 for an int.
Calling p3.Print() will show p2's num, which (in your original code) will be 5, because that's what you set it to before calling p3.Print().
The reason I say it's a very strange class is that instances have a num data member, but Print doesn't print their num, it prints the num of the Parent passed in (if any).
Related
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.
I have a conceptual question regarding the reference of an object in java.
Here Num is an interface
public interface Num {
void sum();
}
Num2 which implements Num
public class Num2 implements Num{
#Override
public void sum() {
System.out.println(getRandom()+getRandom());
}
public int getRandom() {
Random randomNumber = new Random();
int number = randomNumber.nextInt(30);
return number;
}
}
And the main function
Num n = new Num2();
n.sum();
Here I know that n is a reference of object Num2 and n is an pointer pointing to the object Num2. Num2 contains both the method sum and getRandom .But when we try to access method through n reference we can get only sum method. My question is that how can a pointer know which method are contained in Num. How and which information are stored in the stack for the reference during initialization of the object.If I have any misconception correct me.
You are defining the variable n as of type Num interface and hence you can invoke only the methods declared in Num . This resolution I believe is done at the compile time itself. Compiler determines what fields or methods are accessible by using a reference variable based on its type.
But remember the runtime will invoke the method on the actual object type , i.e. the class implementing the interface.
A variable of a class type T can hold a null reference or a reference to an instance of class T or of any class that is a subclass of T.
Look at the below code :
interface A {
void method1();
}
class B implements A {
public void method1() {
}
public void methodB(){
}
}
class C implements A {
public void method1() {
}
public void methodC(){
}
}
public class InterfaceTest {
public void testMethod(A a){
// this is safe because whatever may be the run time type of actual
// object `a` is referring to , that object will always implement
// method1.
a.method1();
// this cannot be allowed because compiler doesn't know
// what will be the actual run time object `a` will refer to
// It may or may not be an object of B.
a.methodB();
}
}
The compiler (not in runtime) is in charge of validate that you treat your object like a Num rather than a Num2
I think the following goes behind it (correct me if I am wrong):
When you create a reference Num n, then somewhere in the memory this get created with its properties.
So there it must be defining the method and such things that can be accessed with this reference.
Now when you refer it to an object, the object is a separate entity in the memory. When you try to access using the reference, the compiler must be using the reference meta-data to determine which method can be invoked using that reference and so on.
You can only access to the method of the type defined to the variable at compile time. Since your n variable is from Num type, you can only use the methods defined in the Num interface. Note that the behavior of these methods will be defined by the real object reference type, which in this case is Num2.
My question is that how can a pointer know which method are contained in Num?
At compile time it will only check that the function or method called by the reference pointer is declared(not necessarily defined) in the class of reference pointer. At runtime entire inheritance tree is parsed in top down fashion and the correct function implementation is selected.
Also the reference pointer that you hace mentioned is in the stack while the actual object is in the heap. And the object has it's class information.Let me give an example -
Animal animal = new Dog();
System.out.println(animal.getClass());
will print class Dog and not class Animal.
In java, when Child extends Parent (or implements) and you write Parent object = new Child(), you have created a Parent reference to a Child object in memory.Once your code is compiled, the JVM will deal with the object in memory and it will know that the reference variable object actually refers to an object of type Child in memory (in your case, that n is of type Num2).
But until then, you have to deal with the compiler. The compiler only cares about the type of the reference, which in this case is Parent (or in your case Num), and as such will only let you call methods off of it that are declared in the Parent (Num) class.
One way to get around this is to do a cast, like so:
((Num2) n).getRandom();
Be sure only to do this if you know for sure that n is (or will be) actually pointing to an Object of type Num2 in memory! Otherwise, you will get a ClassCastException.
Here you are telling the compiler, "Trust me. I know that this is a Num2, so treat it like one."
To sum up:
Num n = new Num2() declares a reference variable and creates an Object in memory
The variable is of type Num, and that's all the Compiler knows
The object created in memory is of type Num2, and the JVM will know this
To run the JVM you have to satisfy the Compiler
In cases like this, You can satisfy the Compiler by casting.
I am new to java and I have some problem on Casting.
I have a class called Parent, and a class called Children, the Children class is the subclass of Parent.
public class Parent
{
int age;
String occupation;
public void print()
{
System.out.println("My age is:"+ age + "and i am a:" + occupation);
}
}
public class Children extends Parent
{
int height;
public static void main(String args[])
{
Children c = new Children();
Parent p = new Parent();
p=c;
c=(Children) p;
/**Here***/
}
}
My problem is, when I add p.XXX after the casting, I only see the age and occupation accessible for instance p. and when I do c.xxx, I see all age, occupation and height accessible.
I thought when I do p=c, p now are considered to be an instance of a children class isn't it? If yes, then why i didnt see the height integer accessible?
And when I do c=(Children)p, an instance of Parent class is assigned to an instance of Children class, and since the Parent instance doesn't have a option, that why we do a casting from parent to children, correct?
I thought when I do p=c, p now are considered to be an instance of a children class isn't it?
No. The type of the variable p is still Parent. The value will be a reference to an instance of Children, but the compiler doesn't take that into account. It only uses the declared type of the variable.
And when I do c=(Children)p, an instance of Parent class is assigned to an instance of Children class, and since the Parent instance doesn't have a option, that why we do a casting from parent to children, correct?
Well you're not changing the instance at all. You're casting an expression of type Parent - the value will be a reference. At execution time, the JVM will ensure that the value is actually a reference to an instance of Children or some subtype (or null) - if it isn't, the JVM will throw an exception.
It's very important to distinguish between variables, references and objects - they're three quite different concepts, and making sure you understand the difference between them will make a lot of other things clearer.
In the following example:
class Base {
int x=10;
Base() {
show();
}
void show() {
System.out.print ("Base Show " +x + " ");
}
}
class Child extends Base {
int x=20;
Child() {
show();
}
void show() {
System.out.print("Child Show " + x +" ") ;
}
public static void main( String s[ ] ) {
Base obj = new Child();
}
}
Why is the output as shown below
Child Show 0 Child Show 20
I thought constructors can only access instance members once its super constructors have completed.
I think what is happening here is that the super constructor is calling the child's show() method because this method was overridden in Child. as it has been overridden but why is the value of x 0 and why is it able to access this method before the super constructor has completed?
I think what is happening here is that the super constructor is calling the child's show() method because this method was overriden in Child.
That is correct
but why is the value of x 0
because it's not initialized yet (x of Child)
and why is it able to access this method before the super constructor has completed?
That's exactly why in a constructor you should never call a method, which can be overridden (non-final public and protected).
Edit:
The strange thing here is that everything has default/ package-private visibility. This can have some strange effects. See: http://www.cooljeff.co.uk/2009/05/03/the-subtleties-of-overriding-package-private-methods/
I recommend to avoid overriding methods with default visibility if possible (you can prevent this by declaring them final).
You can call overriden methods from constructors, but it's bad and you shouldn't. You illustrated the reason why this is bad: the derived class doesn't get a chance to get initialized, so uninitialized fields will be used - in your example, the default for int x is 0, that's why it's printing 0.
constructor chaining it makes sense to explain exactly what that is. A subclass constructor method's first task is to call its superclass' constructor method. This ensures that the creation of the subclass object starts with the initialization of the classes above it in the inheritance chain.
http://java.about.com/b/2009/02/07/java-term-of-the-week-constructor-chaining.htm
http://javahours.blogspot.com/2008/12/constructor-chain.html
Childs override of the show method is invoked because that's what the Java spec calls for. Here is a great discussion of why you should not do it. The value of x is zero because Child has not finished initializing yet.
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.