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.
Related
This question already has answers here:
Dynamic dispatch and binding
(2 answers)
Closed 2 years ago.
Im confused, when i use getClass( ) from a superclass reference variable that's pointing to a subclass object, the result is the subclass.
Heres a simple example:
public `class` TestGetClass
{
public static void main(String[] args)
{
Object obj = new Integer(20);
System.out.println("obj class: " + obj.getClass());
}
}
The output gives me the Integer class instead of the Object class.
obj class: class java.lang.Integer
Can someone explain please
What you're looking for is simply:
Object.class.
obj.getClass() in java could plausibly be interpreted in two different ways:
It means: Take the expression 'obj', which is a reference (i.e., a pointer). Follow the pointer and find the object it is pointing at. Ask that object what its type is.
just like 1, except, because the variable type was Object, invoke the implementation of the getClass() method from the java.lang.Object class. i.e., no dynamic dispatch.
It means: Take the locally declared variable named obj. What type did I declare it as, right here in this method? Don't care about the object/pointer at all, just the declaration.
Now, the java lang spec is crystal clear: In java, #1 is what happens. #2 is not available (you can't opt out of dynamic dispatch. As a matter of obvious language design, private methods don't do it because they don't need it, and static methods don't do it because, by being static, they just aren't a part of the hierarchy in the first place - so those seeming exceptions really don't apply. There is no other way to opt out).
Here's the thing about option #2 though: is completely pointless.
In java, you can't have mystery meat variables. Somebody declares them, and the type is written right there in the source file. There is no such thing as 'eh, figure it all out at runtime'. Even java10's var doesn't work that way (it's still locked in, for sure, at compile time).
So, you already know. It is object, what point is there to repeat it?
If you want a java.lang.Class<?> instance that represents Object, there's syntax for this. it is:
Class<?> objClass = Object.class;
I was having an exam in Java today and the examiner asked me if I can provide any examples of using polymorphism in my Spring Boot project.
As I couldn`t think of anything at first, he pointed out that I have overriden toString() in my models and that this is dynamic/runtime polymorphism.
However, I am not sure that I understand his point, because to my understanding, a behavior is considered polymorphmic when we have a parent class reference variable pointing to a subclass object (focusing on dynamic polymorphism).
Then at runtime the actual object, to which the parent class variable points to, is fetched and its method is called, as explained nicely here.
However, I do not use upcasting in my project (i.e. initializing my POJO classes with an Object class variable).
Thus, my question is - is overriding toString() considered polymorphism, although the parent class (Object) is never used as a reference variable?
All exampes of runtime polymorphism that I find on Stackoverflow, including the ones here and this one with toString, illustrate a situation where we have a parent class variable pointing to a subclass object, e.g:
Object object = new User("petar");
String name = object.toString(); // assign to variable for clarity`s sake
System.out.println(name);
// prints petar
Where my User class is:
public class User {
String name;
public User(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
However, in my project I simply create users and other POJO classes with their own reference variables, e.g:
User user = new User("petar");
String name = user.toString();
System.out.println(name);
// prints petar, as toString is overriden
Is the above considered polymorphism, although there is no upcasting / parent reference variable involved?
My classmate argues that it is, because for non-final instance methods, the compiler doesn`t know which method to call - it only ensures that there is such method in the superclass, so it prolongs this decision up until runtime (late binding) by inserting an instruction into the compiled code, which is checked then and the actual object, to which the variable points to, is fetched, and its method is called (source).
However, in this article it is stated that:
Method Overriding is an example of runtime polymorphism. When a parent
class reference points to the child class object then the call to the
overridden method is determined at runtime, because during method call
which method(parent class or child class) is to be executed is
determined by the type of object. This process in which call to the
overridden method is resolved at runtime is known as dynamic method
dispatch.
So: is method overriding sufficient for polymorphism, or is it a requirement that there is a parent class reference to the subclass object? Am I safe to say at interviews that merely overriding toString() is an example of polymorphism?
Thanks to the comments and a few other sources, I believe I can now answer my question as follows:
One could argue that overriding toString() is an example of polymorphism because:
The Java Virtual Machine (JVM) always selects the method to invoke on non-final instance methods based on the object that it is referenced to, and not the method defined by the variable type. This is known as dynamic method invocation or late binding i.e - the decision which method to call happens at runtime, hence the wording "runtime" polymorphism. Source: Oracle Docs, JavaWorld.
Thus, regardless whether we consciously use polymorphism by e.g. programming to interfaces or we do a simple toString() method override, but still continue to use our classes with their own class variables (i.e. using a "User" variable instead of the parent class "Object" variable), a decision about which method to call is always made on runtime by checking the type of object our variables are referring to.
Thus, the evaluation on which model to call (i.e. the polimorphic behavior) happens, regardless which of the two initializations we use:
User user = new User("username1");
System.out.println(user);
// or
Object object = new User("username1");
System.out.println(object);
The type of the variable is insignificant for our question, what matters is the object that it is referring to, and which of all possible objects it refers to (i.e a parent or a child), is decided on runtime.
The type of the variable is only relevant to either limit the scope of available methods to the ones in the parent class and potentially overridden by its children (if we use a parent class reference variable) or to gain access to the specific methods of the child (if we use a child class reference variable).
For example, if we added a new method to our User class:
public String instanceMethod () {
return "User instance method called";
}
It would not be available through a Object class variable:
It would only be available through a User class variable.
Hope this clears the confusion for everyone else that needs a more detailed explanation too.
What does .class mean in Java? For example, if I created a class called Print. What does Print.class return?
When you write .class after a class name, it references the class literal -
java.lang.Class object that represents information about a given class.
For example, if your class is Print, then Print.class is an object that represents the class Print on runtime. It is the same object that is returned by the getClass() method of any (direct) instance of Print.
Print myPrint = new Print();
System.out.println(Print.class.getName());
System.out.println(myPrint.getClass().getName());
.class is used when there isn't an instance of the class available.
.getClass() is used when there is an instance of the class available.
object.getClass() returns the class of the given object.
For example:
String string = "hello";
System.out.println(string.getClass().toString());
This will output:
class java.lang.String
This is the class of the string object :)
Just to clarify, this '.class' method is not referring to the bytecode file you see after compiling java code nor a confusion between the concepts of Class vs. Object in OOP theory.
This '.class' method is used in Java for code Reflection. Generally you can gather meta data for your class such as the full qualified class name, list of constants, list of public fields, etc, etc.
Check these links (already mentioned above) to get all the details:
https://docs.oracle.com/javase/tutorial/reflect/class/classNew.html
https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html
Normally you don't plan on using Reflection right away when you start building your project. It's something that you know you need after trying to manage already working code. Many times you need it to manage multiple instances of your program. Maybe you want to identify each particular 'clone' to determine if something is already defined, or count the number of functions, or just simply log the details of a particular instance of your class.
If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass()
The .class Syntax
If the type is available but there is no instance then it is possible to obtain a Class by appending .class to the name of the type. This is also the easiest way to obtain the Class for a primitive type.
boolean b;
Class c = b.getClass(); // compile-time error
Class c = boolean.class; // correct
See: docs.oracle.com about class
If there is no instance available then .class syntax is used to get the corresponding Class object for a class otherwise you can use getClass() method to get Class object. Since, there is no instance of primitive data type, we have to use .class syntax for primitive data types.
package test;
public class Test {
public static void main(String[] args)
{
//there is no instance available for class Test, so use Test.class
System.out.println("Test.class.getName() ::: " + Test.class.getName());
// Now create an instance of class Test use getClass()
Test testObj = new Test();
System.out.println("testObj.getClass().getName() ::: " + testObj.getClass().getName());
//For primitive type
System.out.println("boolean.class.getName() ::: " + boolean.class.getName());
System.out.println("int.class.getName() ::: " + int.class.getName());
System.out.println("char.class.getName() ::: " + char.class.getName());
System.out.println("long.class.getName() ::: " + long.class.getName());
}
}
I think the key here is understanding the difference between a Class and an Object. An Object is an instance of a Class. But in a fully object-oriented language, a Class is also an Object. So calling .class gets the reference to the Class object of that Class, which can then be manipulated.
Adding to the above answers:
Suppose you have a a class named "myPackage.MyClass". Assuming that is in classpath, the following statements are equivalent.
//checking class name using string comparison, only Runtime check possible
if(myInstance.getClass().getName().equals(Class.forName("myPackage.MyClass")).getName()){}
//checking actual Class object for equality, only Runtime check possible
if(myInstance.getClass().getName() == Class.forName("myPackage.MyClass"))){}
//checking actual Class object for equality, but compile time validation
//will ensure MyClass is in classpath. Hence this approach is better (according to fail-fast paradigm)
if(myInstance.getClass() == MyClass.class){}
Similarly, the following are also equivalent.
Class<?> myClassObject = MyClass.class; //compile time check
Class<?> myClassObject = Class.forname("myPackage.MyClass"); //only runtime check
If JVM loads a type, a class object representing that type will be present in JVM. we can get the metadata regarding the type from that class object which is used very much in reflection package. MyClass.class is a shorthand method which actually points to the Class object representing MyClass.
As an addendum, some information about Class<?> reference which will be useful to read along with this as most of the time, they are used together.
Class<?> reference type can hold any Class object which represents any type.
This works in a similar fashion if the Class<?> reference is in method argument as well.
Please note that the class "Class" does not have a public constructor. So you cannot instantiate "Class" instances with "new" operator.
A class literal is an expression consisting of the name of a class, interface, array, or primitive type, or the pseudo-type void, followed by a '.' and the token class.
One of the changes in JDK 5.0 is that the class java.lang.Class is generic, java.lang.Class Class<T>, therefore:
Class<Print> p = Print.class;
References here:
https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
http://docs.oracle.com/javase/tutorial/extra/generics/literals.html
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.8.2
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.
I'm training for a Java exam, and I've come across something I don't understand in last year subject. Here is the code
class Mother {
int var = 2;
int getVar() {
return var;
}
}
class Daughter extends Mother {
int var = 1;
int getVar() {
return var;
}
public static void main(String[] args) {
Mother m = new Mother();
System.out.println(m.var);
System.out.println(m.getVar());
m = new Daughter();
System.out.println(m.var);
System.out.println(m.getVar());
}
}
The question is "what is the output of this program?". I would have go with 2 2 1 1, but when compiling and running this piece of code, I get 2 2 2 1.
Anyone can explain me why ?
Thanks for reading !
The method call m.getVar() is a virtual method call. The second time you call it, it's dynamically dispatched to the derived Daughter.getVar(), which does what you expect (accesses Daugther.var and returns that).
There is no such virtual dispatch mechanism for member fields. So m.var always refers to Mother.var, i.e. the base class's version of that variable.
The Daughter class can be seen as having two different var member: the one from Mother and its own. Its own member "hides" the one in Mother, but can be accessed from within the Daughter class by using super.var.
The official spec for this is in section 8.3 Field Declarations of the JLS.
Quote:
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. The field declaration also shadows (ยง6.3.1) declarations of any accessible fields in enclosing classes or interfaces, and any local variables, formal method parameters, and exception handler parameters with the same name in any enclosing blocks.
Note that it can get pretty interesting (emphasis added):
If a field declaration hides the declaration of another field, the two fields need not have the same type.
And:
There might be several paths by which the same field declaration might be inherited from an interface. In such a situation, the field is considered to be inherited only once, and it may be referred to by its simple name without ambiguity.
So that paragraph is well worth reading :-)
Focus on these lines:
Mother m;
m = new Daughter();
System.out.println(m.var);
System.out.println(m.getVar());
You are constructing a Daughter object, but you are treating it like it's base class Mother. So when you access m.var you are accessing the base class variable var. Meanwhile when you call a method, even if you are referring to the base class reference, the overrided method is called.
It's a different behavior for methods and fields.. Fields reference cannot be overrided.
Methods can be overridden however fields can only be hidden. The difference is that a non-static method uses the type of the object referenced, a field takes the type of the reference. You see a similar thing with static methods which only be hidden where the class of the "reference" and the object (if provided) is ignored.
For your interest, try giving the fields different types. ;)
You can also try
System.out.println(((Mother)m).var); // uses var in Mother
System.out.println(((Daughter)m).var); // uses var in Daughter
m = new Daughter();
Though you have created a daughter object, you are referring that object with Mother m reference. So, any call using m will call the Mother class members, not daughter's
I ran this in Eclipse and checked the values with debugger, the debugger actually shows the local m -variable having TWO different var -members after the m = new Daugher() -line with values 2 and 1. m.var seems to resolve to the one in Mother, and the m.getVar() calls the getVar in Daughter (as expected).
However, when I change the main-method to look like this:
Mother m = new Mother();
System.out.println(m.var);
System.out.println(m.getVar());
Daughter d = new Daughter();
System.out.println(d.var);
System.out.println(d.getVar());
It actually outputs 2, 2, 1, 1, so it would seem that the declaration of the variable affects which class's var is used.
I read the answers and non of them (so far) gave good reason why in Object oriented language as Java is, this should be the case. I will try to explain.
Suppose that you have function that takes Mother as arg:
void foo(Mother m) {
print(m.var);
}
This function (actually the compiler) has no idea if you will call it with Mother, Daughter or with another Dauther2 that doesn't even have var variable declared. Because of that, when the reference is of type Mother, reference to a member variable must be linked (by the compiler) to the Mother's member. The similar applies to function too, so the functions are linked to Mother's declaration of getVar(), but not to Mother's implementation of getVar()
So, member variables are always linked (by the compiler) based on the reference. Another way to explain it: If you remove Mother's var (and make Mother's getVar() compilable), your second m.var (when m refers to Daughter) won't compile even Daughter has member var.
I hope i was clear.