This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
The concept of shadowing
I am confused about how the fields of classes are handled in Java during upcasting. For example:
class SuperClass
{
String myString = "String in SuperClass";
public void myMethod()
{
System.out.println("Method in SuperClass");
}
}
class SubClass extends SuperClass
{
String myString = "String in SubClass";
public void myMethod()
{
System.out.println("Method in SubClass");
}
}
class Question
{
public static void main(String[] args)
{
SuperClass test = new SubClass();
// object test is an instance of SubClass
// but I am telling the compiler to treat it as SuperClass
test.myMethod();
System.out.println(test.myString);
}
}
Output:
Method in SubClass
String in SuperClass //Why is "String in SubClass" not used?
When I create an object test it is an instance of SubClass class; however, I am telling the compiler to treat it as SuperClass. Everything is clear to me about methods work: I will only be able to use the methods of the SubClass, if a given method is defined for SuperClass.
However, I am lost as to why a field of a SuperClass is used when I try to access myString of test. Since test is an instance of SubClass I would expect myString defined in SubClass to be used, why is this not happening? What am I missing?
I know that I can access, myString of SubClass by using this operator. For example, I could define printMyString method in SuperClass, and overwrite it with
public void printMyString()
{
System.out.println(this.myString);
}
In the SubClass, so my question is mostly about how come the field of the SuperClass is used in test. Maybe I am missing something obvious?
I tried to search for the answer, and the closest topic I found was Upcasting in Java and two separate object properties, though helpful, it did not answer my question.
Thank You in Advance
Attributes cant be overloaded like methods.
test.myMethod();
Here method invocation depends on the type of actual object. Here object is of type SubClass so method of SubClass is invoked.
test.myString
While accessing attributes,it depends on the type of reference variable. Here reference variable ie test is of type SuperClass so attribute from SuperClass is accessed.
What you are looking is class variable hiding / shadowing.
Fields in Java are only hidden and not actually overridden (that doesn't mean that we'll get a compile time error while trying this, instead they are not overridden in its true sense).
Overriding means the member should be invoked based on the run time
type of the object and not based on the declared type.
But binding for fields in Java is always static and hence it's based on the declared type of the object reference only.
In the example you've given, by declaring the class variable with the name 'myString' in class SubClass you hide the class variable it would have inherited from its superclass SuperClass with the same name 'myString'.
Java language specification :
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, or by using a field access expression that contains the keyword super or a cast to a superclass type.
Related
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 :)
As we know Java is an object oriented language. Everything is objects in Java. We also know that objects have something (instance variables / fields) and do something (methods). Its safe that we change the state of instance variables using methods i.e; setters & getters. So in a constructor we initialize the instance variables. So in other words constructor is doing something for an object. So isn't it correct to presume that constructor is kind of a utility method just like a setter which sets value? The difference is in case of a setter even we have return type void and in constructor we don't have any return type. And setters can be called any number of times on an object but constructor can be called once in a lifetime of an object.
Can we say Contructors are Methods in Java?
If you're new to Java and trying to grasp the concept for the first time, you can think of constructors as factory methods. (Like in Python for instance where a constructor just a method called __init__.) You should however move on quickly and understand that there are many differences. To name a few:
A constructor does not have a return type.
It has special obligations when it comes to initializing final member variables (a method can't even assign to final members).
It's static in the sense that you can invoke it without a callee, but it's non-static in the sense that you have a this reference.
It's invoked with special keyword, new, and has a special bytecode, invokespecial, while instance methods are called by obj.method() which typically compiles to the invokevirtual bytecode.
It must invoke super constructors unless there's a no-arg constructor in super class.
They are never inherited and can not be overridden.
Directly from the JLS (Chapter 8)
A constructor is used in the creation of an object that is an instance of a class (§12.5, §15.9).
The SimpleTypeName in the ConstructorDeclarator must be the simple name of the class that contains the constructor declaration; otherwise a compile-time error occurs.
In all other respects, the constructor declaration looks just like a method declaration that has no result (§8.4.5).
Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding.
Constructor in Java
Java constructor is invoked at the time of object creation. It constructs the values i.e. provides data for the object that is why it is known as constructor.
The constructor actually returns the current class instance (You cannot use return type yet it returns a value).
There are basically two rules defined for the constructor.
1)Constructor name must be same as its class name
2)Constructor must have no explicit return type
Types of constructors
1)Default constructor (no-arg constructor)
class Bike1{
Bike1(){System.out.println("Bike is created");}
public static void main(String args[]){
Bike1 b=new Bike1();
}
}
2)Parameterized constructor
class Student4{
int id;
String name;
Student4(int i,String n){
id = i;
name = n;
}
void display(){System.out.println(id+" "+name);}
public static void main(String args[]){
Student4 s1 = new Student4(111,"Karan");
Student4 s2 = new Student4(222,"Aryan");
s1.display();
s2.display();
}
}
a constructor is used to initialize variables, it is not a method. you can however choose to create constructor, if you do not the JVM will create a default constructor.
This question already has answers here:
Slight confusion regarding overriding where variables are concerned
(6 answers)
Closed 9 years ago.
I am having some doubts about this Java code. The output it gives is "furry bray". My questions:
Why do i get this output?
How can I access the String object reference "name" in ZooKeeper class?
If it has something to do with variable shadowing, then which variable is being shadowed?
Code:
class Mammal {
String name = "furry ";
String makeNoise() { return "generic noise"; }
}
class Zebra extends Mammal {
String name = "stripes ";
String makeNoise() { return "bray"; }
}
public class ZooKeeper {
public static void main(String[] args) { new ZooKeeper().go(); }
void go() {
Mammal m = new Zebra();
System.out.println(m.name + m.makeNoise());
//Output comes as "furry bray". Please explain this.
//And how can we access the name variable, the one having "stripes " in it.
//Does it have something to do with Variable Shadowing?
}
}
Variables aren't polymorphic. When you access m.name, that will always use the Mammal.name field which is part of that object, regardless of the execution-time type of the object. If you need to get access to Zebra.name, you need an expression with a compile-time type of Zebra.
The makeNoise method is called virtually though - the implementation used at execution time does depend on the type of the object.
Note that if you make all your fields private - which is generally a good idea anyway - this doesn't end up being an issue.
This is actually hiding rather than shadowing. See JLS section 8.3 for details on hiding, and section 6.4.1 for shadowing. I can't say that I always keep the differences straight...
Output comes as "furry bray". Please explain this.
fields in java programs are not accessed via dynamic lookup. Instead they are resolved statically while compile time. That's why you are getting furry for m.name. Whereas, methods in java programs are accessed via dynamic lookup. That's why you are getting bray for m.makeNoise().
And how can we access the name variable, the one having "stripes " in
it?
And if you want to access Zebra.name , you should type cast m to 'Zebra'.This would look like this:
System.out.println(((Zebra)m).name + m.makeNoise());
UPDATE
The phenomena that is exhibiting here is the result of Fields Hiding rather than variable shadowing.
There is no variable overriding in Java, you declared name in both the parent and the child but you referred to it through a parent reference variable. That's why you got 'furry'.
There is overriding for methods, which is why you got bray. Because on runtime it looked at the real object in the heap and saw it's a Zebra.
Variable names in Java are resolved by the reference type, not the object they are referencing. So, m.name refers to the variable name in Mammal even dough m is a Zebra.
It happened because your field name from Mammal is just hidden by name field from Zebra. You can then access it simply by casting to required type.
On the other side makeNoise() method overrides same method from parent so you can't access implementation from parent anymore.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Do interfaces inherit from Object class in java
package inheritance;
class A{
public String display(){
return "This is A!";
}
}
interface Workable{
public String work();
}
class B extends A implements Workable{
public String work(){
return "B is working!";
}
}
public class TestInterfaceObject{
public static void main(String... args){
B obj=new B();
Workable w=obj;
//System.out.println(w.work());
//invoking work method on Workable type reference
System.out.println(w.display());
//invoking display method on Workable type reference
//System.out.println(w.hashCode());
// invoking Object's hashCode method on Workable type reference
}
}
As we know that methods which can be invoked depend upon the type of the reference variable on which we are going to invoke. Here, in the code, work() method was invoked on "w" reference (which is Workable type) so method invoking will compile successfully. Then, display() method is invoked on "w" which yields a compilation error which says display method was not found, quite obvious as Workable doesn't know about it. Then we try to invoke the Object class's method i.e. hashCode() which yields a successful compilation and execution. How is it possible? Any logical explanation?
The intuitive answer is that regardless of what interface you refer to, the object implementing the interface must be a subclass of Object.
Section 9.2 of the JLS specifically defines this behaviour: http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.2
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
i.e. all interfaces are assumed to contain method signatures corresponding to methods in the Object class.
I think what's happening here is that even though w is known only to be Workable, all objects must derive from Object, so no matter what class w eventually is, it must have the Object methods.
The reason w.display() doesnt work is as you have save the reference as your interface type. The compiler only sees the methods exposed by the interface. If you were to call ((B)w).display() this would work. You are able to call hashCode() as the compiler is smart enough to know that interfaces are inherited by Objects and all object's superclass is Object
I read somewhere that in Java "constructors are not inherited".
On the other hand, I also read that if I don't explicitly call super, Java automatically calls the super class constructor with no arguments (such a constructor must exist in this case).
Isn't automatically calling the super class constructor (with no arguments) a form of inheritance?
What does "constructors are not inherited" exactly mean?
It means that you cannot create a subclass, using a constructor of the super class-if the subclass did not also declared it. An example;
class A {
A() {}
A(String s) {}
}
class B extends A {
}
Now you cannot do this:
B b = new B("testing");
It means just because your superclass has a contructor doesn't mean the subclass will automatically get the same constructor; you have to define it manually.
The default constructor is kind of an exception and kind of isn't. It's automatically defined for you, but it's not really "inherited" because it's still part of the subclass; it's not a member of the superclass.