This question already has answers here:
Java: Calling a super method which calls an overridden method
(13 answers)
Closed 5 years ago.
Question: The result of the following code is "5 A" and "10 B". How is it possible that for b.print(), this.num is a reference to a Class A object and this.getClass() is a reference to a Class B Object?
Superclass A
public class A {
private int num;
public A(int num) {
this.num = num;
}
public void print() {
System.out.println(this.num + " " + this.getClass().getName());
}
}
Subclass B
public class B extends A {
public B(int num) {
super(num);
}
}
Main Method
A a = new A(5);
B b = new B(10);
a.print();
b.print();
These are two distinct things.
this.getClass() or more simply getClass() (as this is implied as not specified) will always refer to the actual runtime class that may be the class that uses it or a child of it. If you call it from A, it will return the A class but if you call it from a child of it, it will return this child class.
While this.num refers to a specific instance field declared in the A class. When you code refer to this field, it relies necessarily on the class that declares this specific field.
Whenever you call this in an instance, you are going to be calling the actual instance, and not the "class". For example, in you case, if you override the method print in your class B, like this;
public class B extends A {
public B(int num) {
super(num);
}
public void print() {
System.out.println("PRINTING B");
}
}
Then when you call the print method it will call this one and not the parent one, even if you use this.print() inside any method of the class A
If you really want to explicitly print the A class, then you need to reference it like this:
public void print() {
System.out.println(this.num + " " + A.class.getName());
}
Related
This question already has answers here:
Does polymorphism apply on class attributes in Java?
(8 answers)
Closed 4 years ago.
I have a following code
public class Main {
public static void main(String[] args) {
Parent upCasted = new Child();
System.out.println("String: " + upCasted.getString());
System.out.println("Int: " + upCasted.a);
}
}
class Parent {
int a = 1;
public String getString() {
return "Parent";
}
}
class Child extends Parent {
int a = 2;
#Override
public String getString() {
return "Child";
}
}
When I run it I see this in console
String: Child
Int: 1
Why during the upcasting the int value was taken from the Parent and the String value from the Child?
It's because instance fields are not overridden when re-declared in child classes.
Instead, when upCasted.a is evaluated, Java looks at the static/declared type of upCasted to know which class's field to read (not at the runtime class of the object that upCasted points to).
This is why one should not use the same name for fields in superclasses and subclasses.
This question already has answers here:
Why doesn't the compiler complain when I try to override a static method?
(9 answers)
Closed 6 years ago.
I'm new at learning Java can anyone explain me the execution flow of the following code? I'm quite confused with the output.
This is the code:
public class MainClass {
public static void main(String[] args) {
car c = new car();
vehicle v = c;
/* I am unable to understand what's happening while printing the values using the objects of the different classes*/
System.out.println("|" + v.getModelName()
+ "|" + c.getModelName()
+ "|" + v.getRegNo() + "|" + c.getRegNo() + "|");
}
}
class vehicle {
public static String getModelName() {
return "Volvo";
}
public long getRegNo() {
return 12345;
}
}
class car extends vehicle {
public static String getModelName() {
return "Toyota";
}
#Override
public long getRegNo() {
return 54321;
}
}
Object creation
You are creating car instance ( new car())
Add new object pointer to variable c
Copy content of variable c to variable vehicle ( which point to car object)
Method call flow
When you are call static function on object it will not apply inheritance rules, so in call to v.getModelName() Java Virtual Machine call method in class vehicle.
But when you are call car() object with vehicle pointer (v variable) getRegNo method of class vehicle will call and also when you are using car pointer (c variable) getRegNo method of class vehicle will call.
edite suggestion form comment:
This ability called "Polymorphism": here you can find good tutorial. "Polymorphism" is definitely as important a concept as "inheritance" and "encapsulation'.
This question already has answers here:
java constructor: this(.)
(3 answers)
Closed 6 years ago.
Why super have no effect on i field in class C ?
The output is 012, but why not 321, since class B extends class C ?
public class C {
protected int i;
public C(int i){
this(i,i);
System.out.print(this.i);
this.i=i;
}
public C(int i, int j) {
System.out.print(this.i);
this.i=i+j;
}
public C(){
this(1);
System.out.print(i);
}
public static void main(String[] args) {
C c=new C();
}
}
public class B extends C{
public B(){
super.i=3;
}
public static void main(String[] args){
C c=new B();
}
}
super.i just refers to this.i (or simply i) because class B does not declare its own version of i, so it inherits the field from C already.
public B(){
super.i=3; // the super here does not do anything
}
The first thing a constructor needs to do is invoke one of the super constructors. So this is equivalent to:
public B(){
super();
i=3;
}
As you can see, the code in the superclass C is executed before i is set to 3. That's why it prints the old value.
super can be used for accessing overridden methods. In your scenario i is an inherited member of B.
If you override a method in B that was defined in C, you can call it from B by using the super keyword.
It´s quite simple. That´s what is happening:
B Constructor is called.
B doesn´t have an explicit super constructor call- so implicity call super().
C() Constructor is called -> call C(int)
C(int) Constructor is called -> call C(int,int);
C(int, int) is called. print i. i only has the default value yet so print ->0
C(int, int) does increment i by j, which at this point is 1+1 = 2
C(int) Constructor callback, as C(int, int) is done, print i = 2
C(int) sets i = 1 and prints i = 1.
B() callback as C() is done. set instance variable i to 3.
As you can see you have a different output as 021 and that´s everyone that does happen.
I don´t know what your initial intention was, but super can have different meanings.
In the constructor you usually access a parents constructor with super.
by doing super.i you are only accessing the instance variable i of the parent class.
you could, by doing super.testMethod() call an method testMethod from the parentclass
This question already has answers here:
Java Inheritance - instance variables overriding
(3 answers)
Closed 7 years ago.
I have 2 classes A and B such that
public class A {
public String a = "hey";
public void printA() {
System.out.println(a);
}
and
public class B extends A{
public String a = "Jude";
}
What do I need to do so that the output of the lines below is Jude
B object = new B();
object.printA(); //This should output Jude
You cannot access the subclass field from the superclass. However you can change it in subclass like this:
public class B extends A {
B() {
this.a = "Jude";
}
}
This way you don't declare the new field, but change the value of existing one. Note that extends A is necessary to specify that B is subclass of A.
Alternatively you may consider using a method instead of field:
public class A {
public String getA() {
return "hey";
}
public void printA() {
System.out.println(getA());
}
}
public class B extends A {
#Override
public String getA() {
return "Jude";
}
}
Note that in Java "variable" term usually applied to local variables declared within methods. You are speaking about "field", not "variable".
Fields can not be overridden. Methods can; use methods instead:
public class A {
public String getA() {
return "hey";
}
public void printA() {
System.out.println(getA());
}
}
public class B extends A {
public String getA() {
return "Jude";
}
}
That's all. If getA() is not called outside these classes, cincdider making it protected.
Just change your declaration of a to this.a like so.
public class B extends A{
B(){
super();
//Could hardcode this.a to "Jude" here if you want.
}
B(String word){
super();
this.a = word;
}
}
a is already defined for B from the superclass A so you need to use "this" to access it.
You can use it like so
B object = new B("Jude");
object.printA(); //"Jude"
The Java® Language Specification, Java SE 8 Edition
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.
Not sure If I need to further explain it for the audience, but YOU CANNOT "use values of local variables in inherited functions of java", why? See above.
Please have a look at this code :
class Foo {
public int a;
public Foo() {
a = 3;
}
public void addFive() {
a += 5;
}
public int getA() {
System.out.println("we are here in base class!");
return a;
}
}
public class Polymorphism extends Foo{
public int a;
public Poylmorphism() {
a = 5;
}
public void addFive() {
System.out.println("we are here !" + a);
a += 5;
}
public int getA() {
System.out.println("we are here in sub class!");
return a;
}
public static void main(String [] main) {
Foo f = new Polymorphism();
f.addFive();
System.out.println(f.getA());
System.out.println(f.a);
}
}
Here we assign reference of object of class Polymorphism to variable of type Foo, classic polmorphism. Now we call method addFive which has been overridden in class Polymorphism. Then we print the variable value from a getter method which also has been overridden in class Polymorphism. So we get answer as 10. But when public variable a is SOP'ed we get answer 3!!
How did this happen? Even though reference variable type was Foo but it was referring to object of Polymorphism class. So why did accessing f.a not result into value of a in the class Polymorphism getting printed? Please help
You're hiding the a of Polymorphism - you should actually get a compiler warning for that. Therefore those are two distinct a fields. In contrast to methods fields cannot be virtual. Good practice is not to have public fields at all, but only methods for mutating private state (encapsulation).
If you want to make it virtual, you need to make it as a property with accessor methods (e.g. what you have: getA).
This is due to the fact that you can't override class varibles. When accessing a class variable, type of the reference, rather than the type of the object, is what decides what you will get.
If you remove the redeclaration of a in the subclass, then I assume that behaviour will be more as expected.