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.
Related
I'm preparing for the SCJP (recently rebranded as OCPJP by Oracle) and one particular question that I got wrong on a mock exam has confused me, the answer description doesn't explain things clear enough.
This is the question :
class A
{
int x = 5;
}
class B extends A
{
int x = 6;
}
public class CovariantTest
{
public A getObject()
{
return new A();
}
public static void main(String[]args)
{
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
}
}
class SubCovariantTest extends CovariantTest
{
public B getObject()
{
return new B();
}
}
The answer is 5, but I chose 6.
I understand that overriding applies to methods at runtime, and not variables, but the way my mind interpreted that println was :
call getObject on c1
c1 is actually a SubCovariantTest object, and has a valid override
for getObject(), so use the overridden method
The override returns B, so grab x from B which is 6
Is it a case of the JVM ignoring the getObject() part, and always taking x from c1 as variables are associated at compile time?
Although the override is done properly for SubCovariantTest the answer is 5 because of how the variable c1 is declared. It is declared as a CovariantTest and not as a SubCovariantTest.
When c1.getObject().x is run, it does not know that it is a SubCovariantTest (no casting was used). This is why 5 is returned from CovariantTest and not 6 from SubCovariantTest.
If you change
System.out.println(c1.getObject().x);
to
System.out.println(((SubCovariantTest) c1).getObject().x);
you will get 6 as you expected.
Edit: As pointed out in the comments
"fields are not polymorphic in Java. Only methods are. The x in the subclass hides the x in the base class. It doesn't override it." (Thanks to JB Nizet)
Okay I know this is a bit late to reply to this question but I and my friend had the same problem and the answers already here didn't quite clear it for us. So I'll just state what problem I had and how it makes sense now :)
Now I do understand that fields don't get overrided but instead they get hidden as miller.bartek pointed out and I also understand that overriding is for methods and not fields as Scott points out.
The problem I had however was this. According to me,
c1.getObject().x
This must transform into:
new B().x // and not newA().x since getObject() gets overrided
And that evaluates to 6.
And I couldn't get why the variable of class A (super-class) is being called by an object of class B (sub-class) without having explicitly asked for such a behaviour.
And guessing from the wording of the question, I feel the OP had the same question/doubt in mind.
My Answer:
You get a hint from Elbek's answer. Put the following lines in the main method and try to compile the code:
A a = c1.getObject(); //line 1
B b = c1.getObject(); //line 2
You'll notice that line 1 is completely legal while line 2 gives compilation error.
So when the function getObject() is being called, the CovariantTest (super) function IS getting overrided by SubCovariantTest (sub) function since that is valid overriding in the code and c1.getObject() WILL return new B().
However, since the super-function returns a reference of class-type A, even after getting overrided, it must return a reference of class-type A unless ofcourse we type-cast it. And here, class B is a class A (due to inheritance).
So practically, what we're getting from c1.getObject() is not
new B()
but this:
(A) new B()
That is why the output comes out to be 5 even though an object of class B is returned and class B has value of x as 6.
The technical term for what is happening here is "hiding". Variables names in Java are resolved by the reference type, not the object they are referencing.
A object has a A.x variable.
B object has both A.x and B.x variables.
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.
Note that hiding also applies to static methods with the same signature.
Your mock question in a simplified form (without overriding):
class A {
int x = 5;
}
class B extends A {
int x = 6;
}
public class CovariantTest {
public static void main(String[] args) {
A a = new B();
B b = new B();
System.out.println(a.x); // prints 5
System.out.println(b.x); // prints 6
}
}
You are calling method from c1: System.out.println(c1.getObject().x);
c1 reference type is:
public class CovariantTest
{
public A getObject()
{
return new A();
}
public static void main(String[]args)
{
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
}
}
so for this: c1.getObject() return type is A. from A you getting directly attribute not method, as you mention java does not override attributes, so it is grabbing x from A
When methods are overridden, subclass methods are called, and when variables are overridden the superclass variables are used
When the child and parent class both have a variable with same name child class's variable hides parent class's variable and this is called variable hiding.
While variable hiding looks like overriding a variable similar to method overriding but it is not, Overriding is applicable only to methods while hiding is applicable variables.
In the case of method overriding, overridden methods completely replaces the inherited methods so when we try to access the method from parent's reference by holding child's object, the method from child class gets called.
But in variable hiding child class hides the inherited variables instead of replacing, so when we try to access the variable from parent's reference by holding child's object, it will be accessed from the parent class.
When an instance variable in a subclass has the same name as an instance variable in a superclass, then the instance variable is chosen from the reference type.
You can read more on my article What is Variable Shadowing and Hiding in Java.
i want to make sure that my understanding is correct in static-polymorphism
please look at the code below
class a {
int x=0;
}
class b extends a {
int x=4;
}
public class main4 {
public static void main(String[] args) {
a f = new b();
System.out.println(f.x);
b ff = new b();
System.out.println(ff.x);
}
}
the output is
0
4
does that happened because the compiler looks at the declared type of the reference and upon that determines which x to print at compile time ??
(f is declared as type a, the compiler looks at f.x and decides it means a.x)??
& if so,is this called a static-polymorphism or hiding or what ??
thanks in advance
Polymorphism is like looking on the object via the key hole. You don't see the whole object but only that it's part which corresponds to the type of variable you have assigned a reference to the object to.
The object can be seen as different "shapes/forms" - it depends what the key hole you are looking through. But it is still the same object in computer's memory. The form you can see depends on the type of variable you have assigned the object to.
Polymorphism is a multi-form of seeing same object.
If you have object created by new b() - you'll see it as a b class representant when you assign this object to the variable of type b. And you'll see it as a a class representant when you assign it to the variable of type a.
But it is still the same object. And... you can cast it between variables:
f = (a)ff;
and you'll see that suddenly the same object is seen as an representative of a class (including visibility of x field belonging to the a class).
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
Given the follwoing Code:
public class A {
int at=2;
public int m(int i){return at+i;}
}
class B extends A {
int at=3;
public int m(int i){return at+5*i;}
}
public class Main {
public static void main(String args[]){
A x = new B();
System.out.println("Output "+x.m(x.at));
}
}
The output is 13.
How does it work?
I know that it takes method from B, but what about arguments?
Look at expression: x.m(x.at). Since x is cdeclared as A, x.at will refer to at field in A.
However, it gets more complicated when it comes to methods. Although x is declared as A, x in fact is of type B, so method m will be called from x's acctual class, B.
Maybe this coud help.
Actually you have two at fields one declared in A and other in B. Method m in A refers to field at in A; method m in B refers to filed at in B. Method is overridden, field is not. x is declared as instance of A so x.at is 2. When you call method m the overridden method is called (B.m(2)) so you get 3+5*2 = 13.
In such cases Java Language specification should tell you what's right and why. Answer to this question can be found in 8.3. Field Declarations
If the class declares a field with a certain name, then the
declaration of that field is said to hide any and all accessible
declarations of fields with the same name in superclasses, and
superinterfaces of the class.
A hidden field can be accessed by using a qualified name (§6.5.6.2) if
it is static, or by using a field access expression that contains the
keyword super (§15.11.2) or a cast to a superclass type.
cast to a superclass type is your case.
Variables does not override like methods. So variables value depends on Reference Variable not on the instance being referenced by this reference variable.
example: in your case. In main() method
A x =new B();
reference variable x is of type A and it hold a reference of an instance of type B.
So as X is of type A. WhenEver you write x.at it being refer Class A variable.
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.