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.
Related
Parent p = new Child();
Why can't I use print() method in the Parent without overriding it in Child?
public class OverridingMethod {
public static void main(String[] args) {
Parent p = new Child();
// why this does not work
p.print();
}
}
class Parent{
/*
public void print(){
System.out.println("Parent Method");
}
*/
}
class Child extends Parent{
public void print(){
System.out.println("Child Method");
}
}
Parent p = new Child();
Here, we declare a variable called p. Its value is new Child(). As far as this particular line of code is concerned, we're making a Child instance. However, you've assigned it to a variable of type Parent. This is fine; it's called upcasting and it's a fundamental part of inheritance-based polymorphism.
However, because you've done that, the compiler recognizes that p is of type Parent. On all subsequent lines of code, Java has forgotten that p is actually a Child and only assumes that it's a Parent, since that's what you told it to assume. If Parent doesn't know how to print, then we can't print it, because we told Java to forget that we have that functionality. If Parent does know how to print, then we can print it. How we print it is irrelevant; subclasses are free to override that unless the method is final. All that matters is that we can.
Now, Java provides us backdoors into this mechanism. In theory, once we write
Parent p = new Child();
after this line, we should never be able to realize that p is a Child again. We told Java to treat it like any other Parent. Generally, that's good. If you say something is a Parent, you should treat it like one. If you want a Child, you should've asked for a Child. If we really need to, we can "cheat" the type system and see what's really in the box.
if (p instanceof Child) {
Child c = (Child)p;
...
}
Now we've "recovered" the original child. Code that makes frequent use of the above runtime checks if often a sign of a poorly-designed codebase.
I am studying overriding member functions in JAVA and thought about experimenting with overriding member variables.
So, I defined classes
public class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
public class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class mainClass
{
public static void main(String [] args)
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
System.out.println(aRef.intVal);
aRef.identifyClass();
}
}
The output is:
1
I am class A
1
I am class B
I am not able to understand why when aRef is set to b intVal is still of class A?
When you make a variable of the same name in a subclass, that's called hiding. The resulting subclass will now have both properties. You can access the one from the superclass with super.var or ((SuperClass)this).var. The variables don't even have to be of the same type; they are just two variables sharing a name, much like two overloaded methods.
Variables are not polymorphic in Java; they do not override one another.
There is no polymorphism for fields in Java.
Variables decision happens at a compile time so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
1) Base Class variables will be accessed.
2) Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.
Variables are resolved compile-time, methods run-time. The aRef is of type A, therefore aRef.Intvalue is compile-time resolved to 1.
OverRiding Concept in Java
Functions will override depends on object type and variables will accessed on reference type.
Override Function: In this case suppose a parent and child class both have same name of function with own definition. But which function will execute it depends on object type not on reference type on run time.
For e.g.:
Parent parent=new Child();
parent.behaviour();
Here parent is a reference of Parent class but holds an object of Child Class so that's why Child class function will be called in that case.
Child child=new Child();
child.behaviour();
Here child holds an object of Child Class, so the Child class function will be called.
Parent parent=new Parent();
parent.behaviour();
Here parent holds the object of Parent Class, so the Parent class function will be called.
Override Variable: Java supports overloaded variables. But actually these are two different variables with same name, one in the parent class and one in the child class. And both variables can be either of the same datatype or different.
When you trying to access the variable, it depends on the reference type object, not the object type.
For e.g.:
Parent parent=new Child();
System.out.println(parent.state);
The reference type is Parent so the Parent class variable is accessed, not the Child class variable.
Child child=new Child();
System.out.println(child.state);
Here the reference type is Child, so the Child class variable is accessed not the Parent class variable.
Parent parent=new Parent();
System.out.println(parent.state);
Here the reference type is Parent, so Parent class variable is accessed.
From JLS Java SE 7 Edition §15.11.1:
This lack of dynamic lookup for field accesses allows programs to be run efficiently with straightforward implementations. The power of late binding and overriding is available, but only when instance methods are used.
Answers from Oliver Charlesworth and Marko Topolnik are correct, I would like to elaborate a little bit more on the why part of the question:
In Java class members are accessed according the type of the reference and not the type of the actual object. For the same reason, if you had a someOtherMethodInB() in class B, you wouldn't be able to access it from aRef after aRef = b is run. Identifiers (ie class, variable, etc names) are resolved at compile time and thus the compiler relies on the reference type to do this.
Now in your example, when running System.out.println(aRef.intVal); it prints the value of intVal defined in A because this is the type of the reference you use to access it. The compiler sees that aRef is of type A and that's the intVal it will access. Don't forget that you have both fields in the instances of B. JLS also has an example similar to yours, "15.11.1-1. Static Binding for Field Access" if you want to take a look.
But why do methods behave differently? The answer is that for methods, Java uses late binding. That means that at compile time, it finds the most suitable method to search for during the runtime. The search involves the case of the method being overridden in some class.
I hope this can help:
public class B extends A {
// public int intVal = 2;
public B() {
super();
super.intVal = 2;
}
public void identifyClass() {
System.out.println("I am class B");
}
}
So overriding variable of base class is not possible, but base class variable value can be set (changed) from constructor of inherited class.
This is called variable hiding. When you assign aRef = b; , aRef has two intVal, 1 is named just intVal another is hidden under A.intVal (see debugger screenshot), Because your variable is of type class A , even when you print just intVal java intelligently picks up A.intVal.
Answer 1: One way of accessing child class's intVal is System.out.println((B)aRef.intVal);
Answer 2: Another way of doing it is Java Reflection because when you use reflection java cant intelligently pickup hidden A.intVal based on Class type, it has to pick up the variable name given as string -
import java.lang.reflect.Field;
class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class Main
{
public static void main(String [] args) throws Exception
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
Field xField = aRef.getClass().getField("intVal");
System.out.println(xField.get(aRef));
aRef.identifyClass();
}
}
Output -
1
I am class A
2
I am class B
Well, I hope u got the answer. If not, you can try seeing in the debug mode. the subclass B has access to both the intVal. They are not polymorphic hence they are not overriden.
If you use B's reference you will get B's intVal. If you use A's reference , you will get A's intVal. It's that simple.
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
Hence the variable in the sub class only can be seen as one sharing the same name.
Also when the constructor of A is called during the instance creation of B the variable (intVal) is initialized and hence the output.
It is because when you assign b to aRef, it is resolved, leading aRef to just be of class A. This means that aRef does not have access to any of class B's fields or methods. If you call for intVal instead by using b.intVal, you will get 2.
Java has a feather of encapsulation means it tightly binds the property and the behavior of an object. so only via a class reference we can call it's behavior to change it's property.
and in inheritance only method overrides so that it can affects only it's property.
As Many users have already pointed out, this is not polymorphism. Polymorphism only applies to methods(functions).
Now as to why the value of the intVal of class A is printed, this happens because as you can see the reference aRef is of type A.
I can see why you are confused by it. By the same procedure you have accessed the overridden methods for ex. the method identifyClass() but the not the variables which directly proves the first line that I have written .
Now in order to access the variable you can do ((Superclass)c).var
Note here that the Superclass can be many levels up for example
A<-B<-C. That is C extends B and B extends A. If you wanted the value of var of A then you could have done ((A)c).var .
EDIT: as one of the users have pointed out this 'trick' does not apply to static methods, because they are static.
I am studying overriding member functions in Java and thought about experimenting with overriding member variables.
So, I defined classes
public class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
public class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class mainClass
{
public static void main(String [] args)
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
System.out.println(aRef.intVal);
aRef.identifyClass();
}
}
The output is:
1
I am class A
1
I am class B
I am not able to understand why when aRef is set to b intVal is still of class A?
When you make a variable of the same name in a subclass, that's called hiding. The resulting subclass will now have both properties. You can access the one from the superclass with super.var or ((SuperClass)this).var. The variables don't even have to be of the same type; they are just two variables sharing a name, much like two overloaded methods.
Variables are not polymorphic in Java; they do not override one another.
There is no polymorphism for fields in Java.
Variables decision happens at a compile time so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
1) Base Class variables will be accessed.
2) Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.
Variables are resolved compile-time, methods run-time. The aRef is of type A, therefore aRef.Intvalue is compile-time resolved to 1.
OverRiding Concept in Java
Functions will override depends on object type and variables will accessed on reference type.
Override Function: In this case suppose a parent and child class both have same name of function with own definition. But which function will execute it depends on object type not on reference type on run time.
For e.g.:
Parent parent=new Child();
parent.behaviour();
Here parent is a reference of Parent class but holds an object of Child Class so that's why Child class function will be called in that case.
Child child=new Child();
child.behaviour();
Here child holds an object of Child Class, so the Child class function will be called.
Parent parent=new Parent();
parent.behaviour();
Here parent holds the object of Parent Class, so the Parent class function will be called.
Override Variable: Java supports overloaded variables. But actually these are two different variables with same name, one in the parent class and one in the child class. And both variables can be either of the same datatype or different.
When you trying to access the variable, it depends on the reference type object, not the object type.
For e.g.:
Parent parent=new Child();
System.out.println(parent.state);
The reference type is Parent so the Parent class variable is accessed, not the Child class variable.
Child child=new Child();
System.out.println(child.state);
Here the reference type is Child, so the Child class variable is accessed not the Parent class variable.
Parent parent=new Parent();
System.out.println(parent.state);
Here the reference type is Parent, so Parent class variable is accessed.
From JLS Java SE 7 Edition §15.11.1:
This lack of dynamic lookup for field accesses allows programs to be run efficiently with straightforward implementations. The power of late binding and overriding is available, but only when instance methods are used.
Answers from Oliver Charlesworth and Marko Topolnik are correct, I would like to elaborate a little bit more on the why part of the question:
In Java class members are accessed according the type of the reference and not the type of the actual object. For the same reason, if you had a someOtherMethodInB() in class B, you wouldn't be able to access it from aRef after aRef = b is run. Identifiers (ie class, variable, etc names) are resolved at compile time and thus the compiler relies on the reference type to do this.
Now in your example, when running System.out.println(aRef.intVal); it prints the value of intVal defined in A because this is the type of the reference you use to access it. The compiler sees that aRef is of type A and that's the intVal it will access. Don't forget that you have both fields in the instances of B. JLS also has an example similar to yours, "15.11.1-1. Static Binding for Field Access" if you want to take a look.
But why do methods behave differently? The answer is that for methods, Java uses late binding. That means that at compile time, it finds the most suitable method to search for during the runtime. The search involves the case of the method being overridden in some class.
I hope this can help:
public class B extends A {
// public int intVal = 2;
public B() {
super();
super.intVal = 2;
}
public void identifyClass() {
System.out.println("I am class B");
}
}
So overriding variable of base class is not possible, but base class variable value can be set (changed) from constructor of inherited class.
This is called variable hiding. When you assign aRef = b; , aRef has two intVal, 1 is named just intVal another is hidden under A.intVal (see debugger screenshot), Because your variable is of type class A , even when you print just intVal java intelligently picks up A.intVal.
Answer 1: One way of accessing child class's intVal is System.out.println((B)aRef.intVal);
Answer 2: Another way of doing it is Java Reflection because when you use reflection java cant intelligently pickup hidden A.intVal based on Class type, it has to pick up the variable name given as string -
import java.lang.reflect.Field;
class A{
public int intVal = 1;
public void identifyClass()
{
System.out.println("I am class A");
}
}
class B extends A
{
public int intVal = 2;
public void identifyClass()
{
System.out.println("I am class B");
}
}
public class Main
{
public static void main(String [] args) throws Exception
{
A a = new A();
B b = new B();
A aRef;
aRef = a;
System.out.println(aRef.intVal);
aRef.identifyClass();
aRef = b;
Field xField = aRef.getClass().getField("intVal");
System.out.println(xField.get(aRef));
aRef.identifyClass();
}
}
Output -
1
I am class A
2
I am class B
Well, I hope u got the answer. If not, you can try seeing in the debug mode. the subclass B has access to both the intVal. They are not polymorphic hence they are not overriden.
If you use B's reference you will get B's intVal. If you use A's reference , you will get A's intVal. It's that simple.
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
Hence the variable in the sub class only can be seen as one sharing the same name.
Also when the constructor of A is called during the instance creation of B the variable (intVal) is initialized and hence the output.
It is because when you assign b to aRef, it is resolved, leading aRef to just be of class A. This means that aRef does not have access to any of class B's fields or methods. If you call for intVal instead by using b.intVal, you will get 2.
Java has a feather of encapsulation means it tightly binds the property and the behavior of an object. so only via a class reference we can call it's behavior to change it's property.
and in inheritance only method overrides so that it can affects only it's property.
As Many users have already pointed out, this is not polymorphism. Polymorphism only applies to methods(functions).
Now as to why the value of the intVal of class A is printed, this happens because as you can see the reference aRef is of type A.
I can see why you are confused by it. By the same procedure you have accessed the overridden methods for ex. the method identifyClass() but the not the variables which directly proves the first line that I have written .
Now in order to access the variable you can do ((Superclass)c).var
Note here that the Superclass can be many levels up for example
A<-B<-C. That is C extends B and B extends A. If you wanted the value of var of A then you could have done ((A)c).var .
EDIT: as one of the users have pointed out this 'trick' does not apply to static methods, because they are static.
We have parent class and child class having common method testparent() but there is difference in parameters
//Parent Class
public class Overriding {
int a,b,c;
//Parameters are different in number
public void testParent(int i, int j) {
System.out.println(a+b);
}
}
//Child Class Extending Parent Class Method
class ChildOverriding extends Overriding {
int c;
public void testParent(int i,int j,int k) {
System.out.println(a+b+c);
}
//Main Is not getting executed????
public static void main(String args[]) {
Overriding obj = new ChildOverriding();
obj.testParent(1,4,8);
}
}
}
Overriding Means sub class should have same signature of base class method.
Parameters and return type should be the same.
Actually your problem here is that you're accessing a method from SubClass over a reference object of a SuperClass.
Let me explain little bit more.
Super obj = new Sub();
This line will create one reference variable (of class Super) named obj and store it in stack memory and instance of new Sub() with all implementation details will be stored in heap memory area. So after that memory address of instance stored in heap is linked to reference variable stored in stack memory.
obj.someMethod()
Now when we call any method (like someMethod) on reference variable obj it will search for method signature in Super class but when it calls implementation of someMethod it will call it from instance stored in heap memory area.
That's the reason behind not allowing mapping from Super to Sub class (like Sub obj = new Super();) becuase Sub class may have more specific method signature that can be called but instance stored in heap area may not have implementation of that called method.
So your program is giving error just because it isn't able to find method signature that you're calling in super class.
Just remember Java will always look for method signature in type of reference object only.
Answer to your question is Yes, we can have different number of parameters in subclass's method but then it won't titled as method overloading/overriding. because overloading means you're adding new behaviour and overriding means changing the behaviour.
Sorry for my bad English, and if I'm wrong somewhere please let me know as I'm learning Java.
Thanks. :)
You can have the two methods, but then the one in ChildOverriding are not overriding the one in Overriding. They are two independent methods.
To fix your compilation problem, you have to either declare obj ChildOverriding
ChildOverriding obj = new ChilOverriding();
or you have to also implement a three-argument method in Overriding
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).