Accessing parent class field "this.field" VS "super.field" - java

I want to know the difference between accessing parent class fields using this and super.
We have the following abstract class named ListItem which extends Node class.
public abstract class ListItem {
protected ListItem rightLink=null;
abstract ListItem next();
}
And the following code inside the Node class:
public class Node extends ListItem {
#Override
ListItem next() {
return this.rightLink;
}
But if we use the code super.rightLink, I do not get any error at compile time or runtime. I just want to know what is the difference between the both and is there a best practice to accomplish the task?

Explanation
It does not matter in this case, there is no difference.
The field is declared in the parent class. So technically super.rightLink would makes the most sense. However, super and this are only relevant for resolving ambiguous situations with variable shadowing.
The best in this case would be to leave out any prefix and just type rightLink. But this is a bit opinion-based.
Example
Suppose we have the following
public class Parent {
int variable = 1; // Field
}
public class Child extends Parent {
int variable = 2; // Field
public void foo() {
int variable = 3; // Local variable
System.out.println(variable); // 3
System.out.println(this.variable); // 2
System.out.println(super.variable); // 1
}
}
In-depth
So we have a situation with 3 different variables which all live in a different scope, but they have the same name. When you just type variable, Java will refer to the variable with the lowest scope. Which would be the local variable in the method.
If you want to access your field, you need to do this.variable. If you want to access the field of your parent, you need to do super.variable.
So again, we have three different variables here.
no prefix: lowest scope
this: field with lowest scope
super: field with lowest scope, starting from the direct parent
In your specific example, however, we have no name shadowing at all. There is only one variable with the name rightLink. So all three variants refer to the exact same variable.
The best in this case would be to use no prefix at all, just rightLink.
JLS
Let us see how the Java Language Specification defines this. and super..
For this., refer to JLS§15.8.3:
When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method or default method was invoked (§15.12), or to the object being constructed. The value denoted by this in a lambda body is the same as the value denoted by this in the surrounding context.
For super., refer to JLS§15.11.2:
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.

Unless rightLink is marked as private, it will be accessible in all classes deriving from ListItem. Thus, call super.rightLing and this.rightLink will be equivalent.
Generally, super refers to base class and this refers to class you are in. Use them appropraitely.
It's commonly used when overriding methods, i.e.
#Override
public void DoSomething(){
// Execute base imlpementation of a method
super.DoSomething();
// some additional code to add extra functionality to base class
}

Related

Java instance variable resolution in Java is confusing;

I am studying for my OCA exam and came across this problem and It is very confusing.
Variable resolution always based on reference type instead of the runtime object. So if my parent and child class look like this:
class Parent {
public int x = 1;
public int getX() {
return x;
}
}
class Child extends Parent {
public int x = 2;
public int getX() {
return x;
}
}
Based on the rules (variable resolution is always based on reference type), the following code is behaving as expected:
Child c = new Child();
System.out.println(c.x); //2
System.out.println(((Parent) c).x); //1
However. if I retrieve the variables by using the getter defined in the parent and child class, then I get this:
Child c = new Child();
System.out.println(c.getX()); //2
System.out.println(((Parent) c).getX()); //2
Shouldn't it print the same as if I was to access the variable directly? why would getting the variable via getter be different than getting the variable directly?
One theory I have is this:
Since instance method resolution is based on runtime object, therefore it overrides the variable resolution rule. In other words, the compiler will resolve the getter methods to the child class since instance method resolution is based on runtime object. Am I right?
Thank you
Methods and variables behave differently. Variables do not get inherited or participate in polymorphism.
The Parent and Child classes each have their own distinct variable x. One doesn't override the other. You can use the cast to specify that you want the Parent's x, not the Child's.
With the method, it doesn't matter what cast you stick on it, when calling the Child you get the overridden version of getX. (Within a method of the Child you can call super.getX to get the parent's version of the method.)
TLDR: variable resolution rules don't apply to methods. Polmorphism doesn't apply to variables.
System.out.println(((Parent) c).getX()); //2
This dispatches to Child.getX() because of polymorphism. Then the variable resolution rules apply in the context of this method. They aren't overridden. So yes, you are essentially correct.
Polymorphism is a mechanism applied before calling a method, which always looks for the most specific override in the whole chain of subclasses, regardless of the instance's declared type.
There is no such mechanism for fields. Giving the two variables the same name "x" does not connect them in any way, so giving those two fields the same name will likely only serve to confuse future readers of your code.

Why is the "this" keyword used in Constructor and Setters?

A constructor is used to initialize a value and assign it to the class variable in the time of creating the class instance, right?
public class Joke{
private String jokeSetup;
private String jokePunchLine;
public Joke(String jokeSetup , String jokePunchLine){
this.jokeSetup=jokeSetup;
this.jokePunchLine=jokePunchLine;
}
}
Consider the following:
public Joke(String jokeSetup , String jokePunchLine)
Is another variable with same name created?
If so, why are they assigned to the former jokeSetup and jokePunchLine values?
PS:This code is not created by me.It was shown in the videos from which I am learning Java.
The purpose of a constructor is to initialize the object that was just created, for instance by filling in its instance fields (also called instance variables). this is used in your constructor to refer to the instance the constructor is initializing.
In your example constructor, you have parameters and instance fields. The constructor is taking the values of the parameters and assigning those values to the instance fields:
public Joke(String jokeSetup , String jokePunchLine)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---- Declares parameters this
// constructor accepts when
// called
{
// vvvvvvvvv------------ parameter
this.jokeSetup=jokeSetup;
// ^^^^^^^^^^^^^^---------------------- instance field
// vvvvvvvvvvvvv---- parameter
this.jokePunchLine=jokePunchLine;
// ^^^^^^^^^^^^^^^^^^------------------ instance field
}
The constructor could initialize instance fields with constant values instead, or by using a parameter value indirectly (for instance, looking something up), etc. It's not always a direct one-to-one assignment as it is in your example.
In your example, the parameters have the same names as the instance fields, but that's not a requirement. For instance, this constructor does exactly the same thing as yours:
public Joke(String theJokeSetup , String theJokePunchLine)
// ^---------------------^---------- Note the name changes
{
// vvvvvvvvvvvv------------ parameter
this.jokeSetup = theJokeSetup;
// ^^^^^^^^^^^^^^--------------------------- instance field
// vvvvvvvvvvvvvvvv---- parameter
this.jokePunchLine = theJokePunchLine;
// ^^^^^^^^^^^^^^^^^^----------------------- instance field
}
Java lets you leave off the this. part when referring to an instance field and just use the field name on its own (e.g. jokeSetup instead of this.jokeSetup). You can't do that in your constructor unless you rename the parameters, though, because they have the same names as the instance fields, so jokeSetup in your constructor is the parameter, not the field. When there's a conflict like that, the most local identifier takes precedence (in your constructor, the parameter is the most local).
When there's no conflict, it's a matter of style whether you use the this. part or not. (I always use this., I find it clearer.) So for instance, here's another version of that constructor which does exactly the same thing as your original:
public Joke(String theJokeSetup , String theJokePunchLine)
// ^---------------------^---------- Note the name changes
{
// vvvvvvvvvvvv------------ parameter
jokeSetup = theJokeSetup;
// ^^^^^^^^^--------------------------- instance field
// vvvvvvvvvvvvvvvv---- parameter
jokePunchLine = theJokePunchLine;
// ^^^^^^^^^^^^^----------------------- instance field
}
I mention this because, again, when there's no conflict, it's a matter of style, and you'll see this style used sometimes.
The class has a field named jokeSetup.
The method has a parameter of the same name that shadows that field.
So in essence there are two variables with the same name.
Using this makes it possible to again differentiate the two different usages of the same name, as this.whatever always denotes the corresponding field.
And you nailed it: shadowing is actually not a good idea. But this "pattern" is actually very common in Java. You could avoid it by giving the parameter a different name, such as _jokeSetup, but deviating from common practices is also bad practice.
A parametrized constructor can be used to initialize value to the variables in the time of creating it. When the parameters and variable names are same then in this case to differentiate between both, we use this keyword. This keyworord always refer to local variable of the method or class.
Java has an implied context for symbol names; the class instance (ie this) for non-static contexts and the class (eg Joke) for static.
This lets you omit the context when there is no conflict for the symbol name. For example
public String getJokeSetup() {
return jokeSetup; // no "this." required, it's implied
}
When there is a conflict for the name such as the case with a method argument named the same as a field, you need to explicitly define the context, eg
public void setJokeSetup(final String jokeSetup) {
// you must prefix the field with "this." to differentiate it from the argument
this.jokeSetup = jokeSetup;
}
Finally, here's an example that avoids a symbol name conflict
public void setJokeSetup(final String js) {
jokeSetup = js;
}
It is fairly typical to name arguments the same as the fields they correspond to but you're certainly not constricted to such a convention.

Why does Java bind variables at compile time?

Consider the following example code
class MyClass {
public String var = "base";
public void printVar() {
System.out.println(var);
}
}
class MyDerivedClass extends MyClass {
public String var = "derived";
public void printVar() {
System.out.println(var);
}
}
public class Binding {
public static void main(String[] args) {
MyClass base = new MyClass();
MyClass derived = new MyDerivedClass();
System.out.println(base.var);
System.out.println(derived.var);
base.printVar();
derived.printVar();
}
}
it gives the following output
base
base
base
derived
Method calls are resolved at runtime and the correct overridden method is called, as expected.
The variables access is instead resolved at compile time as I later learned.
I was expecting an output as
base
derived
base
derived
because in the derived class the re-definition of var shadows the one in the base class.
Why does the binding of variables happens at compile time and not at runtime? Is this only for performance reasons?
The reason is explained in the Java Language Specification in an example in Section 15.11, quoted below:
...
The last line shows that, indeed, the field that is accessed does not depend on the run-time class of the referenced object; even if s holds a reference to an object of class T, the expression s.x refers to the x field of class S, because the type of the expression s is S. Objects of class T contain two fields named x, one for class T and one for its superclass S.
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...
So yes performance is a reason. The specification of how the field access expression is evaluated is stated as follows:
If the field is not static:
...
If the field is a non-blank final, then the result is the value of the named member field in type T found in the object referenced by the value of the Primary.
where Primary in your case refers the variable derived which is of type MyClass.
Another reason, as #Clashsoft suggested, is that in subclasses, fields are not overriden, they are hidden. So it makes sense to allow which fields to access based on the declared type or using a cast. This is also true for static methods. This is why the field is determined based on the declared type. Unlike overriding by instance methods where it depends on the actual type. The JLS quote above indeed mentions this reason implicitly:
The power of late binding and overriding is available, but only when instance methods are used.
While you might be right about performance, there is another reason why fields are not dynamically dispatched: You wouldn't be able to access the MyClass.var field at all if you had a MyDerivedClass instance.
Generally, I don't know about any statically typed language that actually has dynamic variable resolution. But if you really need it, you can make getters or accessor methods (which should be done in most cases to avoid public fields, anyway):
class MyClass
{
private String var = "base";
public String getVar() // or simply 'var()'
{
return this.var;
}
}
class MyDerivedClass extends MyClass {
private String var = "derived";
#Override
public String getVar() {
return this.var;
}
}
The polymorphic behaviour of the java language works with methods and not member variables: they designed the language to bind member variables at compile time.
In java, this is by design.
Because, the set up of fields to be dynamically resolved would make things to run a bit slower. And in real, there's not any reason of doing so.
Since, you can make your fields in any class private and access them with methods which are dynamically resolved.
So, fields are made to resolved better at compile time instead :)

Java variable look up based on type not object [duplicate]

I'm wondering why Java has this strange behavior regarding a superclass and a subclass having instance variables with the same name.
Let's say we have the following class definitions:
class Parent {
int var = 1;
}
class Child extends Parent {
int var = 2;
}
By doing this, we are supposed to have hidden the superclass's variable var. And if we do not explicitly specify a way to access Parent's var via a super call, then we should never be able to access var from an instance of a child.
But when we have a cast, this hiding mechanism breaks:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.var); // prints out 1, instead of 2
Doesn't this completely circumvent the whole point of field hiding? If this is the case, then doesn't that render the the idea completely useless?
EDIT: I am referring specifically to this article in the Java Tutorials. It mentions
Within the subclass, the field in the superclass cannot be referenced
by its simple name. Instead, the field must be accessed through super...
From what I read there, it seems to imply that the developers of Java had some kind of technique in mind in doing this. Though I agree that it is a rather obscure concept and would probably bad practice in general.
In Java, data members are not polymorphic. This means that Parent.var and Child.var are two distinct variables that happen to have the same name. You're not in any sense "overriding" var in the derived class; as you have discovered yourself, both variables can be accessed independently of one another.
The best way forward really depends on what you're trying to achieve:
If Parent.var should not be visible to Child, make it private.
If Parent.var and Child.var are two logically distinct variables, give them different names to avoid confusion.
If Parent.var and Child.var are logically the same variable, then use one data member for them.
The "point" of field hiding is merely to specify the behaviour of code which does give a variable the same name as one in its superclass.
It's not meant to be used as a technique to genuinely hide information. That's done by making the variables private to start with... I would strongly recommend using private variables in virtually all cases. Fields are an implementation detail which should be hidden from all other code.
Attributes are not polymorphic in Java, and anyway declaring a public attribute is not always a good idea. For the behavior you're looking for, it's better to use private attributes and accessor methods, like this:
class Parent {
private int var = 1;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
class Child extends Parent {
private int var = 2;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
And now, when testing it, we get the desired result, 2:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.getVar());
This scenario is known as variable hiding, When the child and parent class both have a variable with the same name, child class's variable hides parent class's variable and this process is called variable hiding.
In Java variables are not polymorphic and Variable Hiding is not same as Method Overriding
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.
public static void main(String[] args) throws Exception {
Parent parent = new Parent();
parent.printInstanceVariable(); // Output - "Parent`s Instance Variable"
System.out.println(parent.x); // Output - "Parent`s Instance Variable"
Child child = new Child();
child.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(child.x);// Output - "Child`s Instance Variable"
parent = child; // Or parent = new Child();
parent.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(parent.x);// Output - Parent`s Instance Variable
// Accessing child's variable from parent's reference by type casting
System.out.println(((Child) parent).x);// Output - "Child`s Instance Variable"
}
As we can see in above 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.
Declaring variables with the same name in both child and parent create confusion we should always avoid it so there will be no confusion. And this is why we should also always stick to General Guidelines to create POJOs and declare our variables with private access and also provide proper get/set methods to access them.
You can read more on my article What is Variable Shadowing and Hiding in Java.
When you are casting, you effectively tell the compiler "I know better" - it suspends the normal strong-typing inference rules and gives you the benefit of a doubt.
By saying Parent parent = (Parent)child; you are telling the compiler "treat this object as if it were an instance of Parent".
On another note, you are confusing "information hiding" principle of OO (good!) with a field-hiding side-effect (usually bad).
As you pointed out:
we are supposed to have hidden the superclass's variable var
The main point here is Variables do not override as methods do, so when you call directly Child.var you are calling a variable directly from the Child class and when you call Parent.var you're calling a variable from the Parent class, no matter if they do have the same name.
As a side note I would say this is really confusing and shouldn't be allowed as valid syntax.

I dont understand this inheritance functionality

Consider the following illegal code :-
class WrongCode{
int i;
static int i;
}
Here, the compiler says that we have duplicate fields in the same class.
Now, consider the following classes in the same file.
class Parent{
int i = 10;
}
class Child extends Parent{
static int i = 100;
}
public class Main{
public static void main(String ... aaa){
Parent ob = new Child();
System.out.println(ob.i); // This prints Parent's i
}
}
Since the actual object is of Child, shouldn't ob refer to Child's i? And if it is refering to Parent's "i", then in a way it is also having Parent's "i" in its own class along with its own static "i" which is NOT ALLOWED.
Child static i overshadows Parent i. And Parent's i is not static, so then how is it accessed directly using instance and not className?
You have instance field i in Parent class and it remain an instance field in Child class.
System.out.println(ob.i); // must be 10
Have a look at - Oracle Java Tutorial - Hiding Fields
It is important to realize here that there is no way System.out.println(ob.i); could print Child's i: it only knows that ob is of declared type Parent, not that it was instantiated with an actual Child. Thus, if Parent did not have any i, there would be a compile error. If parent has an i, this is printed.
I have seen it mentioned on SO that access of class variables via instances (i.e. ob.i being equivalent to Parent.i) should be considered a serious design flaw of Java. I agree it can be sometimes confusing. Anyway, both your parent and child could also have a non-static i and it need not be the same. The argument above should be applicable to reasoning which one would be printed in which situation.
In ob, the static int i of child is never visible since ob is of type Parent, irrespective of how it was instantiated( base class or derived class).
That's why you have the value as 10, that Parents i value.
When you access class member fields (instance variables) like ob.i. you'll get the results from the class that's known at compile time, not what is known at run time. Thats why you have value as 10 which is parents value.
For method calls they are dispatched at run time to an object of the actual class the reference points.
Regarding shadowing here is what Java lang spec says:
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 (if it is static)
language spec
You may refer "Field Declarations" section.
Actually its polymorphism and ob have access only to parent class fields and behaviuors if any...
Java lets your class have its own variables that have the same name as a variable in the parent. But it can't just let you randomly redefine parent variables, as that would cause other stuff to break. So what it does...when you have a variable obj that's declared as the parent class, even if it holds an instance of a child class, obj.i will refer to the parent class's i rather than the child's.

Categories