Why can methods be overriden but attributes can't? - java

I have a class
public class A {
public String attr ="A attribute";
public void method() {
System.out.println(this+" , "+this.attr);
}
public String toString() {
return("Object A");
}
}
and another class that inherits from it
public class B extends A{
public String attr = "B attribute";
public void method() {
super.method();
}
public String toString() {
return("Object B");
}
}
Note that the method() of B is simply a wrapper for method() of A.
When I run the following code
B b = new B();
b.method();
I get Object B , A attribute as output which means that, this and this.attr accessed different things. Why is that the case?
Shouldn't System.out.println(this) refer to the toString() method of class A ?

By declaring a method with a same name as parent class, you override it, that is, replace the original behaviour. But if you declare a field with a same name, you effectively hide it, making it inaccessible from that subclass, but only by super.field. See oracle docs on variable hiding, as well as using the keyword super. Note that it is not recommended to use variable hiding, as it creates exactly the kind of confusion you're experiencing.
By calling super.method(), printing this results in calling the toString method, which was in fact overridden - so that's the reason why it prints "Object B", as you've called the method on an instance of B. But the this in this.attr actually refers to the parent object, as you're calling the method from the parent class (by super.method()).

Related

Java inheritance: Reducing visibility in a constructor vs inherited method

In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.

how to understand super in java

I encountered a problem that confused me, it is the keyword 'super', my test code is like this:
package test;
public class Parent {
private String name;
public Parent(){
this.name = "parent";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void showName(){
System.out.println(this.name);
}
}
public class Child extends Parent{
public Child(){
this.setName("Child");
}
public void showName(){
System.out.println(super.getClass().toString());
System.out.println(super.toString());
super.showName();
System.out.println(super.getName());
}
}
public class Test {
public static void main(String[] args) {
Child d = new Child();
d.showName();
}
}
so the result is like this:
class test.Child
test.Child#2207d8bb
Child
Child
my understanding about 'super' is that it is a reference to the parent instance of current instance, so my expecting output is like 'Parent', from the result , I am wrong, its like the current instance calls the parent method, and 'super' is not parent instance, is my understanding right ? and is there a way that I can get parent instance only initializing the Child class ?
my understanding about 'super' is that it is a reference to the parent instance of current instance
No - there's no such thing as a "parent instance". When you create an instance, there's only one object created - an instance of Child, which inherits all the fields and methods from Parent as well.
super is used in two ways:
To refer to the superclass implementation of a method, typically when you've overridden the method in the subclass. This is what you're doing in Child.showName - it's calling Parent.showName, but on the same instance (because there is only one instance)
To call a superclass constructor from a subclass constructor
From the javadocs, getClass returns the runtime class of an object.
The runtime class of your object is "Child".
As you did not override getClass() (you can't because it's final), so super.getClass() acts exactly like getClass(). getClass method of the Object class is called.
If you want to print the Parent, call getClass().getSuperclass()
You have used four print statements invoked using Child object:
System.out.println(super.getClass().toString());
Since the getClass() is final method thus it cant be overridden, so when you invoke super.getClass(), you actually invoke the Object class's getClass() which returns the name of the class of the actual invoking object.
System.out.println(super.toString());
Here again the toString() method of Object class is invoked which returns
"getClass().getName() + "#" + Integer.toHexString(hashCode());"
However, if you override this method in your parent class you will definitely get that version executed
super.showName();
this method returns "Child".... here's why: When you create an object of Child class the contructor runs as follows-
public Child(){
super(); // this is implicitly called by the compiler even if you did not write this
this.setName("Child");
}
So following action take place - 1. Parent class's contructor is called which sets the 'name' to 'parent'. 2. Child class's contructor now overwrites this valus with 'Child'.
So the value of instance variable 'name' is 'Child'.
System.out.println(super.getName());
Here as said in point 3 the there is only one object and one instance variable 'name' whose value is 'Child'.
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void anotherEat() {
super.eat();
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eat();
d.anotherEat();
}
}
The output is going to be
animal : eat
dog : eat
animal : eat
The third line is printing "animal:eat" because we are calling super.eat(). If we called this.eat(), it would have printed as "dog:eat".

How many objects are created due to inheritance in java?

Let's say I have three classes:
class A {
A() {
// super();
System.out.println("class A");
}
}
class B extends A {
B() {
// super();
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get called
}
}
When I create an instance of class C, it calls the constructor of super class. So, is there more than one object that is getting created? If only one object is created, then how is super() like another class' constructor? Does super() method internally create an object? What I know is, the constructor is also a method (I may be wrong).
My questions are:
How many number of Object is created in this case?
If one object is created then how does Super() internally call the parent class constructor?
Great question. What you are probing is how Java initializes objects - and there are a number of steps involved.
i know is constructor is also a method (Maybe i am wrong).
Nearly right. The Constructor is a special method. If you decompile a class file, you'll see the constructors get renamed to <init>. <init> is treated differently from other methods and, for example, can't be called explicitly except through use of the keyword new or super. This is so fundamental that it is implemented in the JVM itself rather than being something defined in the Java language.
How many number of Object is created in this case.
One object is created - an instance of C.
C is additionally and simultaneously an instance of B and an instance of A and also Object.
If one object is created then how internally super() is calling Parent class Constructor . How Super is able to call parent class constructor.
This is where we get into initialization - initialization is how the JVM creates a new instance of an object and sets all the member values - those of the specific class and those of the superclasses. There are several stages involved:
Load all the referenced classes and initialize those classes. Class initialization is itself non-trivial so I won't cover it here. It is well worth reading up.
Allocate a chunk of memory for holding the members of the instance, which will include the all members of A, B and C. NOTE this explains one aspect of your question: how can the constructors of the base class and its subclasses update or refer to the same object - all the members of the instance from all classes are stored one after the other in the same chunk of memory.
Initialize all the members to their default value. For example, int and float members will be set to 0 and 0.0f.
Execute or calculate the member initializers, eg:
private int a = 10;
private int b = a * 5;
private String c = Singleton.getInstance().getValue();
Note (1) that member initialization occurs strictly in the order that members are declared in the class. This means that references to members later in the declaration are broken:
private int a = b * 5; // Forward reference; won't compile
private int b = 10;
Note (2) that there is a under-used facility in Java to run arbitrary code to initialize values before the constructor is executed. These code blocks are executed at this time again strictly in order of declaration:
private int a;
private int b = 1;
{
// Initization occurs after b but before c.
// c cannot be referenced here at all
int i = SomeClass.getSomeStatic();
a = i * 2;
}
private int c = 99;
Execute the constructor of C. Constructors must either directly invoke a constructor from the superclass or the compiler will automatically add super() as the first line of the constructor. This means that the constructors are strictly executed in order:
Object
A
B
C
The object is now initialized and is ready for use. You can do some dangerous stuff if you initialize value using instance methods:
public class Wrong {
int a = getB(); // Don't do this!
int b = 10;
public int getB() {
return b;
}
}
Here, a is initialized to 0. This is because, at the point getB() is invoked, Java has cleared the value of b to the default (0), but has not yet set it to 10 in the second phase of initialization.
In summary - there is only one object and it is created and initialized in a number in stages. During those stages, the object is, by definition, not completely defined.
There will be one and only one object will be created and ie. A object.
You can imagine like when class A extends B, then all methods and variables are copied to class A.
In Code only one object will be created and super call the parent class constructor .
Prove of object creation :
package one;
public class A {
public static A super_var;
public A() {
super_var = this;
System.out.println("Constrcutor of A invoked");
}
}
package two;
public class B extends A {
public static A sub_var;
public B() {
sub_var = this;
System.out.println("Constructor of B invoked");
}
public void confirm() {
if (sub_var == A.super_var)
System.out.println("There is only one object is created");
else
System.out.println("There are more than one object created");
}
public static void main(String Args[]) {
B x = new B();
x.confirm();
}
}
This will prove that there will be only one object created.
And about Super().
What I know that it call Parent class constructor . and each constructor ahve Super() as first statement like you mention in your code . so that you know
I don't know how it internally call super class constructor .
Hope this will make you understand there is only the instace you create in program
In your case only, 1 objects is getting created.
When subclasses constructor is called, it calls the constructor of super class internally to initailize super class's members.
Invoking constructor does not mean you are creating objects. Object is already created when invoking the constructor.The objects is created by the JVM first(i.e memory is allocated on heap and then constructor is called).
Constructor are meant for initializing the members of objects.
Your classes will be internally converted to something like this
class A
{
A(){
super();
System.out.println("class A");
}
}
class B extends A{
B(){
super();
System.out.println("class B");
}
}
public class C extends B
{
public static void main(String args[])
{
C c = new C(); //Parent constructor will get call
}
}
How many number of Object is created in this case.
Only one, which is instance of C, calling super() just invokes the constructor of parent class and doesn't create object
If one object is created then how internally Super() is calling Parent
class Constructor . How Super is able to call parent class
constructor.
When you create C's instance. C's constructor gets called, which first calls B's constructor, which in turn calls A's constructor
How many number of Object is created in this case.
When you create an instance of Class C by C cInstance = new C(); a single instance(Object) of Class C is creates(None of A and B). However since C extends B and B extends A, C will have all the methods of Class A and B(Actually depends on access modifiers used but lets say for this case they are public or default).
If one object is created then how internally Super() is calling Parent class Constructor
. How Super is able to call parent class constructor.
That is how inheritance works. When a new object is created it will call it's super class constructor and that super class will call it's super class constructor and so on. In other ordinary function you have to explicitly call super(). So calling super class constructor goes bottom-up fashion while execution goes top-down fashion of the inheritance hierarchy tree
If you look at dynamics of object allocation as per this SO answer, it must be clear that using new operator, you create only one object per statement. To further clarify the doubt that there is only one object which is being created, go thru this program:
public class A {
public static int aInstanceCount=0;
public static A aInstance;
public String aInstanceVariable;
A() {
//Super();
aInstanceCount++;
aInstanceVariable="aInstanceVar";
System.out.println("class A");
aInstance=this;
}
}
class B extends A {
public static int bInstanceCount=0;
public static B bInstance;
public String bInstanceVariable;
B() {
//Super();
bInstanceCount++;
bInstanceVariable="bInstanceVar";
System.out.println("class B");
bInstance=this;
}
}
class C extends B {
public static void main(String args[]) {
int instanceCount=0;
C c = new C(); //Parent constructor will get call
if(A.aInstance!=null){
instanceCount++;
System.out.println("Value of aInstanceVariable: "+A.aInstance.aInstanceVariable);
}
if(B.bInstance!=null){
instanceCount++;
System.out.println("Value of bInstanceVariable: "+B.bInstance.bInstanceVariable);
}
A a=A.aInstance;
B b=B.bInstance;
System.out.println("bInstanceVariable of B earlier: " + B.bInstance.bInstanceVariable);
//Now we are changing the bInstanceVariable of c which is inherited from B
c.bInstanceVariable="bInstance After modified by C";
System.out.println("bInstanceVariable of B after: " + B.bInstance.bInstanceVariable);
System.out.println("aInstanceVariable of A earlier: " + A.aInstance.aInstanceVariable);
//Now we are changing the aInstanceVariable of c which is inherited from A
c.aInstanceVariable="aInstance After modified by C";
System.out.println("bInstanceVariable of A after: " + A.aInstance.aInstanceVariable);
}
}
The output:
class A
class B
Value of aInstanceVariable: aInstanceVar
Value of bInstanceVariable: bInstanceVar
bInstanceVariable of B earlier: bInstanceVar
bInstanceVariable of B after: bInstance After modified by C
aInstanceVariable of A earlier: aInstanceVar
bInstanceVariable of A after: aInstance After modified by C
If you can notice, the super constructor is implicitly getting called each time if a subclass object is created, but since the new operator is used only once, there is only one object which is actually allocated the space. And by modifying the aInstanceVariable via C object c, we are actually changing the aInstanceVariable of aInstance. So it clearly proves that there is actually one object.
Steps of object creation when you call a constructor to create object:
Memory allocation using init is done. This init makes a system call to allocate memory for object creation.
Then your constructor is called to initialize the object's fields.
Then it calls super class constructor (If there's any super class) and Step 1 through 3 repeats.
What you see when you decompile a class file using javap shows different calls to be made. init makes system call to initialize memory allocation but object's field are initialized when constructor's code is run.
I am not sure how polymorphism/overriding works at the time of GC.
But it should be worth a try to override finalize method in all your classes and check when JVM exits main method.
If only C object is created, it should call finalize for 'C'.
If all A,B, C object is created, it should call finalize for A,B, C.
I think this is simplest check you can apply.
class A {
A() {
//Super();
System.out.println("class A");
}
public void finalize(){
System.out.println("Class A object destroyed");
}
}
class B extends A {
B() {
//Super();
System.out.println("class B");
}
public void finalize(){
System.out.println("Class B object destroyed");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get call
}
public void finalize(){
System.out.println("Class C object destroyed");
}
}
I agree with the previously posted answers, but want to add a reference to the ultimate authority on this issue, the Java Language Specification.
The expression new C() is a "Class Instance Creation Expression". Section 15.9.4 Run-time Evaluation of Class Instance Creation Expressions describes the run time steps involved in creating an object. Note that it refers to "the object", and only allocates space once, but states "Next, the selected constructor of the specified class type is invoked. This results in invoking at least one constructor for each superclass of the class type."
This all becomes much clearer by distinguishing between creating a new object, and invoking a constructor. Invoking a constructor only does part of object creation, the part that runs initializers, superclass constructors, and the body of the constructor. Because a C is also a B, the B constructor has to run during creation of a C.
The super keyword enables a subclass to call the methods and fields of its superclass. It is not an instance of the superclass object but a way to tell the compiler which methods or fields to reference. The effect is the same as if the subclass is calling one of its own methods.
Examples:
Consider a subclass Employee that extends its superclass Person:
public class Employee extends Person{
public Employee()
{
//reference the superclass constructor
super();
}
public String getName()
{
//reference superclass behaviors
return super.getFirstName() + " " + super.getLastName();
}
}
The super keyword can be used to reference the constructer of the Person class or any of the behaviors or fields that it has access to (e.g., getFirstName() and getLastName()).
In your Case One object is created
while doing the following, this super() will provided by Compiler Implicitly
class A {
A() {
System.out.println("class A");
}
}
class B extends A {
B() {
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //
}
}
It is similar to calling a super() inside your methods
B() {
super();
System.out.println("class B");
}
The super keyword can also be used when a method is overridden in the current class, but you want to invoke the super class method.
super() will makes the all constructors reference to one class. (For easy understanding: Its like all the member functions are comes under a same class.)
Its going to call all the constructor methods only.
So its done the work of calling constructor only, so super() will not done any object creation. Its just referring the member functions.
If you add one more line of Code System.out.println(this.hashCode()) will remove your confusion.
Here in All Case hashCode() will print same hashCode all the time. It means there is one and only one unique Object is Created.
class A {
A() {
// super();
System.out.println(this.hashCode()); // it will print 2430287
System.out.println("class A");
}
}
class B extends A {
B() {
// super();
System.out.println(this.hashCode()); // it will print 2430287
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get called
System.out.println(this.hashCode()); // it will print 2430287
}
}
but there is two Constructor is getting invoked to initialize the Parent member variable. I think if you know the concept of super() keyword which invokes the Constructor of parent Class and Initialize the member Variable of parent Class.
3 constructors will call
Code:
class A
{
A()
{
System.out.println("In A");
}
}
class B extends A
{
B()
{
System.out.println("In B");
}
}
class C extends B
{
C()
{
System.out.println("In C");
}
}
public class InheritanceTest {
public static void main(String args[])
{
C c1=new C();
}
}
Output:
In A
In B
In C

T and inheritance in Java

I have a class A with static field F:
class A {
public static String F = null;
}
Class B:
class B extends A {
public static String F = "somestring";
}
and a typed class with a method that uses field F:
class C<T extends A> {
public void someMethod() {
String someString = T.F;
// Manipulations with someString
}
}
And then my code that calls it.
C<B> c = new C<B>();
c.someMethod();
and I'm getting a null pointer exception when trying to manipulate with someString. So, the T.F is null, but T is B, so it should be "somestring"! Why?
You can't Override fields. Since it is extends A, it will always use the field in A.
Add a getter in class A and B that returns F. From there, Override the method in A with the one in B.
class A {
public String getF(){
return null;
}
}
class B {
#Override
public String getF(){
return "someString";
}
}
This doesn't have to do with generics.
The fields of a class cannot be overridden by a subclass - only methods can. So, even if you define a field in your subclass with the same name as the one in the superclass, you're merely creating a new field that simply happens to have the same name but actually shadows (not overrides) the previous one.
Consider putting an assignment with the default value of the field in the constructor of your subclass. Then it should work.
A static member in Java can be hidden, but not overridden. A reference to a static member is resolved at compile time - and at compile time, the only known type of T is A.
See http://www.coderanch.com/how-to/java/OverridingVsHiding.
Edit: A field cannot be overridden anyway, whether it is static or instance.
This happens because all the static members of A are common to A alone and cannot be inherited by B.
No new static member, which is not present in A, can be present in B.
Virtually, when you say
class C < T extends A > {
...
}
You can only use methods(both static and instance - unless #Overriden) and fields which are common in A. So, since F is not an instance field, it is not overriden and the JVM finds the occurance of F in A.
Hence you get an NPE.

Java compiler super() constructor generals [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of ‘super’ keyword when accessing non-overridden superclass methods
I'm new to Java and have been reading a lot about it lately to get more knowledge and experience about the language. I have a question about inherited methods and extending classes when the compiler inserts automatic code.
I've been reading that if I create class A with some methods including lets say a method called checkDuePeriod(), and then create a class B which extends class A and its methods.
If I then call the method checkDuePeriod() within class B without using the super.checkDuePeriod() syntax, during compilation will the compiler include the super. before checkDuePeriod() or will the fact that the compiler includes the super() constructor automatically when compiling the class imply the super. call of the methods that class B calls from class A?
I'm a little confused about this. Thanks in advance.
The super class's implementation of regular methods is not automatically invoked in sub classes, but a form of the super class's constructor must be called in a sub class's constructor.
In some cases, the call to super() is implied, such as when the super class has a default (no-parameter) constructor. However, if no default constructor exists in the super class, the sub class's constructors must invoke a super class constructor directly or indirectly.
Default constructor example:
public class A {
public A() {
// default constructor for A
}
}
public class B extends A {
public B() {
super(); // this call is unnecessary; the compiler will add it implicitly
}
}
Super class without default constructor:
public class A {
public A(int i) {
// only constructor present has a single int parameter
}
}
public class B extends A {
public B() {
// will not compile without direct call to super(int)!
super(100);
}
}
If you call checkDuePeriod() in B without super., means you want to invoke the method that belongs to the this instance (represented by this within B) of B. So, it equivalent to saying this.checkDuePeriod(), so it just doesn't make sense for the compiler to add super. in the front.
super. is something that you must explicitly add to tell the compiler that you want to call the A's version of the method (it is required specially in case B has overridden the implementation provided by A for the method).
Call of super() as a default constructor (constructor with no args) can be direct or non direct but it garants that fields of extendable class are properly initialized.
for example:
public class A {
StringBuilder sb;
public A() {
sb = new StringBuilder();
}
}
public class B extends A {
public B() {
//the default constructor is called automatically
}
public void someMethod(){
//sb was not initialized in B class,
//but we can use it, because java garants that it was initialized
//and has non null value
sb.toString();
}
}
But in case of methods:
Methods implement some logic. And if we need to rewrite logic of super class we use
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
//new check goes here
}
}
and if we want just implement some extra check, using the value returned from checkDuePeriod() of superclass we should do something like this
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
if(super.checkDuePeriod()){
//extra check goes here
}else{
//do something else if need
}
return checkResult;
}
}
First about the Constructors:
- When ever an object of a class is created, its constructor is initialized and at that time immediately the constructor of its super-class is called till the Object class,
- In this process all the instance variables are declared and initialized.
- Consider this scenario.
Dog is a sub-class of Canine and Canine is a sub-class of Animal
Now when Dog object is initialized, before the object actually forms, the Canine class object must be form, and before Canine object can form the Animal class object is to be formed, and before that Object class object must be form,
So the sequence of object formed is:
Object ---> Animal ---> Canine ---> Dog
So the Constructor of the Super-Class is Called before the Sub-Class.
Now with the Method:
The most specific version of the method that class is called.
Eg:
public class A{
public void go(){
}
}
class B extends A{
public static void main(String[] args){
new B().go(); // As B has not overridden the go() method of its super class,
// so the super-class implementation of the go() will be working here
}
}

Categories

Resources