My code is:
class Foo {
public int a=3;
public void addFive() {
a+=5;
System.out.print("f ");
}
}
class Bar extends Foo {
public int a=8;
public void addFive() {
this.a += 5;
System.out.print("b ");
}
}
public class TestClass {
public static void main(String[]args) {
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
Output:
b 3
Please explain to me, why is the output for this question "b 3" and not "b 13" since the method has been overridden?
F is a reference of type Foo, and variables aren't polymorphic so f.a refers to the variable from Foo which is 3
How to verify it?
To test this you can remove a variable from Foo , it will give you compile time error
Note: Make member variable private and use accessors to access them
Also See
Why use getters and setters?
You cannot override variables in Java, hence you actually have two a variables - one in Foo and one in Bar. On the other hand addFive() method is polymorphic, thus it modifies Bar.a (Bar.addFive() is called, despite static type of f being Foo).
But in the end you access f.a and this reference is resolved during compilation using known type of f, which is Foo. And therefore Foo.a was never touched.
BTW non-final variables in Java should never be public.
With such a question, the SCJP exam is assessing your knowledge of what is known as hiding. The examiner deliberately complicated things to try to make you believe that the behavior of the program depends only on polymorphism, wich it doesn't.
Let's try to make things a bit clearer as we remove the addFive() method.
class Foo {
public int a = 3;
}
class Bar extends Foo {
public int a = 8;
}
public class TestClass {
public static void main(String[]args) {
Foo f = new Bar();
System.out.println(f.a);
}
}
Now things are a bit less confusing. The main method declares a variable of type Foo, which is assigned an object of type Bar at runtime. This is possible since Bar inherits from Foo.The program then refers to the public field a of the variable of type Foo.
The error here would be to believe that the same kind of concept known as overriding applies to class fields. But there is no such a concept for fields: the public field a of class Bar is not overriding the public field a of class Foo but it does what is called hiding. As the name implies, it means that in the scope of the class Bar, a will refer to Bar's own field which has nothing to do with Foo's one. (JLS 8.4.8 - Inheritance, Overriding, and Hiding)
So, when we are writing f.a, which a are we referring to? Recall that resolution of the field a is done at compile time using the declaring type of the object f, which is Foo. As a consequence, the program prints '3'.
Now, lets add an addFive() method in class Foo and override it in class Bar as in the exam question. Here polymorphism applies, therefore the call f.addFive() is resolved using not the compile time but the runtime type of object f, which is Bar, and thus is printed 'b '.
But there is still something we must understand: why the field a, which was incremented by 5 units, still sticks to the value '3'? Here hiding is playing around. Because this is the method of class Bar which is called, and because in class Bar, every a refers to Bar's public field a, this is actually the Bar field which is incremented.
1) Now, one subsidiary question: how could we access the Bar's public field a from the main method? We can do that with something like:
System.out.println( ((Bar)f).a );
which force the compiler to resolve the field member a of f as Bar's a field.
This would print 'b 13' in our example.
2) Yet another question: how could we work around hiding in addFive() method of class Bar to refer not to the Bar's a field but to its superclass eponimous field ? Just adding the super keyword in front of the field reference does the trick:
public void addFive() {
super.a += 5;
System.out.print("b ");
}
This would print 'b 8' in our example.
Note that the initial statement
public void addFive() {
this.a += 5;
System.out.print("b ");
}
could be refined to
public void addFive() {
a += 5;
System.out.print("b ");
}
because when the compiler is resolving the field a, it will start to look in the closest enclosing scope from within the method addFive(), and find the Bar class instance, eliminating the need to use explicitely this.
But, well, this was probably a clue for the examinee to solve this exam question !
Since you are doing f.a you will get the value of a from the class Foo. if you had called a method to get the value, e.g getA() then you would have gotten the value from the class Bar.
Related
class A {
public int a = 100;
}
class B extends A {
public int a = 80;
}
class C extends B {
public int a = 10;
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
}
}
What does ((A) this).a in the line System.out.println(((A) this).a); do?
Is it upcasting/downcasting thisor is something else happening here?
I also tried System.out.println(this); and System.out.println((A)this); and they both have the same output. What exactly is happening here?
In the java programming language, we have classes. When we write java code, we create instances of those classes, for example:
Object o = new Object();
Object is a class. Writing new Object() creates an instance of that class. The above code declares a variable o and assigns it [a reference to] an instance of class Object.
In the terminology of the java programming language, we say that variable o has type Object.
In the code in your question, a variable that is assigned an instance of class C, really has three types.
It has type C.
It has type B since B is the superclass of C.
It has type A because it indirectly extends class A also.
In the context of the code in your question, this is a special variable whose type is C. Writing (A) this is telling java to relate to the variable this as if its type is A.
Class A cannot access its subclasses. Hence it is only aware of its class member a. Hence when you write this line of code...
((A) this).a
You are accessing the member of class A only.
System.out.println(a);a is the one from the show method of your C class → a = 0
System.out.println(super.a);a is the one from the super-class of C, which is B → a = 80
System.out.println(((A) this).a);First, you cast your C instance (this) into A, then you call a which is a member of the A class → a = 100
There is also something to consider : method will always take the more specialized one (except if super is used), where field will be taken directly from the type referenced (even if there is an extending class).
For example, if I add getA() in each classes :
class A {
public int a = 100;
public int getA(){
return a;
}
}
class B extends A {
public int a = 80;
public int getA(){
return a;
}
}
class C extends B {
public int a = 10;
public int getA(){
return a;
}
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
System.out.println(getA());
System.out.println(super.getA());
System.out.println(((A) this).getA());
}
}
class Scratch {
public static void main(String[] args) {
new C().show();
}
}
I get the following output :
0
80
100
10
80
10
Which means that in the case of the method, except in the case of super.getA() which explicitly goes to the superclass, casting your C into a A doesn't change much for methods, as it impacts the field.
If you write something like obj.a, obj.getA() or someMethod(obj), Java somehow has to find the actual field or method to be used, based on the type or class of obj. There are two distinct dispatch mechanisms involved (plus the special construct super).
Dynamic dispatch (polymorphism, overriding): This is used when calling an instance method on the object, as in obj.getA(). Then the runtime class of the obj is examined, and if this class contains a getA() method, this is used. Otherwise, the direct parent class is examined for a getA() method, and so on up to the Object class.
Static dispatch: In cases like obj.a or someMethod(obj), the runtime class of obj doesn't matter. Involved is only the compiler, and from his knowledge of obj's type, he decides which field or method to use.
super dispatch: If you write super.getA() or super.a, your getA() method or a field is ignored, and instead the next-higher class in the hierarchy is used that contains such a method or field.
In your case you have 3 fields plus one local variable, all with the same name a. (By the way, it's a very bad idea to have such name conflicts in professional code.) We are inside a method show() declared in the C class. Let's have a look at some different expressions and what they mean here:
a references the local variable a. There's no dispatch needed, it's just that local definitions take precedence over fields.
this.a is a static-dispatch expression, so it's important what the compiler thinks about the type of this. And that's always the class where this code has been written. In your case, it's class C, so the field a from class C is used, the one being 10.
super.a is a super-dispatch expression, meaning that the a field from this class C is ignored and the next higher one taken (the one from B, in our case).
((A) this).a is static dispatch, but the (A) casting has a significant effect. The expression before the dot originally comes from this, being of type C, but the (A) cast tells the compiler to believe it were of type A. This is okay, as every C also is an A, by inheritance. But now, static dispatch sees something of type A in front of the dot, and dispatches to the a field from the A class, and no longer from C.
getA(), this.getA() and ((A) this).getA() are all dynamic-dispatch examples, all giving the same result. The method called will be the one based on the runtime class of this object. This will typically be one defined in the C class. But if show() was called on an object of a subclass of C, e.g. D, and D had its own getA() method, that one would be used.
super.getA() is a case of super-dispatch, it will call the getA() method next higher up in the class hierarchy from the current class, e.g. B.
System.out.println(this);
And
System.out.println((A)this)
These two prints the object reference to class C with toString() method.
System.out.println(((A)this).a);
This is upcasting, child object to parent object.
class A {
private int foo;
void bar(B b) { b.foo = 42; }
}
class B extends A { }
This fails to compile with the error:
A.java:3: error: foo has private access in A
void bar(B b) { b.foo = 42; }
^
1 error
Adding a cast to the base class makes it work.
void bar(B b) { ((A) b).foo = 42; }
Can someone point me to an explanation about why the first snippet is illegal? What's the reason it's prohibited? Here's what the JLS says:
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
As best I can tell, my code meets this wording. So is this a bug with the Java compiler, or is my interpretation of the JLS incorrect?
(Note: I'm not looking for workarounds, like making the variable protected. I know how to work around this.)
Error message "has a private access in A" is a java bug for a very very long time.
JDK 1.1:
JDK-4096353 : JLS 6.6.1: When subclass references are used to access privates of superclasses
contains code snippet exactly conforms the question one
class X{
private static int i = 10;
void f() {
Y oy = new Y();
oy.i = 5; // Is this an error? Is i accessable through a reference to Y?
}
}
class Y extends X {}
They tried to fix it and it leads to
JDK-4122297 : javac's error messages are not appropriate for a private field.
======TP1======
1 class C extends S {
2 void f(){
3 java.lang.System.out.println("foo");
4 }
5 }
6
7 class S {
8 private int java;
9 }
======
% javac C.java
C.java:3: Variable java in class S not accessible from class C.
java.lang.System.out.println("foo");
^
C.java:3: Attempt to reference field lang in a int.
java.lang.System.out.println("foo");
^
2 errors
======
But by specification java isn't inherited in C and this program should compile.
It fixed in 1.2, but appears in 1.3 again
JDK-4240480 : name00705.html: JLS6.3 private members should not be inherited from superclasses
JDK-4249653 : new javac assumes that private fields are inherited by a subclass
And when generics come
JDK-6246814 : Private member of type variable wrongly accesible
JDK-7022052 : Invalid compiler error on private method and generics
However, by the JLS this member simply doesn't exist in the inherited type.
JLS 8.2. Class Members
Members of a class that are declared private are not inherited by subclasses of that class.
So b.foo is illegal because class B has no field named foo.
It is no restriction, it is an absent field in B.
Java has strong typing and we cannot access fields that do not exist in B even if they exist in superclass A.
Cast (A) b is legal because B is a subclass of A.
A has a field named foo and we can access this private field because b(B b) is a function in class A even if b != this due to
JLS 6.6.1. Determining Accessibility
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Also if we write
class A {
private int foo;
void baz(A b) { b.foo = 42; }
}
class B extends A { }
class T {
void x() {
B b = new B();
b.baz(b);
}
}
It will compile because Java infer type arguments for polymorphic calls.
JLS 15.12.2.7. Inferring Type Arguments Based on Actual Arguments:
A supertype constraint T :> X implies that the solution is one of supertypes of X. Given several such constraints on T, we can intersect the sets of supertypes implied by each of the constraints, since the type parameter must be a member of all of them. We can then choose the most specific type that is in the intersection
You can't say b.foo because foo is private and thus will not be inherited, as a result the B class can't see the foo variable and is not aware if a variable named foo even exist - unless its marked protected (as you said) or default (as they are in the same package i guess) or public.
If you want to use foo without using an explicit cast like your second example you must use this.foo or just foo which has an implicit this. As Javadocs specified, the this keyword main reason is to prevent that:
The most common reason for using the this keyword is because a field
is shadowed by a method or constructor parameter.
When you used ((A) b) you are casting the reference type and the compiler will see it like if you are using an A reference variable type, in other words something like A a, and a.foo is completely legal.
An illustrated summary of visibility and access to superclass's private instance variables:
The specification for field access expressions, chapter 15.11 says:
If the identifier does not name an accessible member field in type T,
then the field access is undefined and a compile-time error occurs.
From the perspective of super class, looking at the types, I'd argue that the member is not accessible, hence the error.
I think the case you're presenting is closer to accessing a member as a field, which is shown in example 15.11-1-1.
class S { int x = 0; }
class T extends S { int x = 1; }
class Test1 {
public static void main(String[] args) {
T t = new T();
System.out.println("t.x=" + t.x + when("t", t));
S s = new S();
System.out.println("s.x=" + s.x + when("s", s));
s = t;
System.out.println("s.x=" + s.x + when("s", s));
}
static String when(String name, Object t) {
return " when " + name + " holds a "
+ t.getClass() + " at run time.";
}
}
Just to answer your question:
Kindly explain what sort of bad code the restriction is protecting
against.
Please consider following snippet.
public class X {
private int a;
public void bar(Z z) {
z.a // not visible, but if was, what 'a'
// would you actually access at this point 'X' or 'Z'
}
}
public class Z extends X {
private int a;
}
It looks to me that the spec is inconsistent. As John states, the body of the spec states
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
and there is no mention of subclasses. So class A should compile correctly. However example 6.6-5 states
A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor. It is not inherited by subclasses.
This second statement is both weaker (no only if), but brings subclasses to the table. According to this A should not compile.
Java is finicky about accessing private variables via a reference type that shouldn't have access to that variable. You should be able to do this legally by writing ((A) b).foo = 42.
We can't inherit the private fields or methods. So in your code Class B is completely unaware of variable foo even though you're accessing from its own class A.
Isn't this what the default access modifier is for?
Try this :
public class blah{
static class A {
int foo;
void bar(B b) {b.foo=42;}
}
static class B extends A {
}
}
You cannot access the private member directly from an ancestor, that is what private means. Now why does it work when you cast? And does that mean the documentation is incorrect?
I mentioned to a colleague that the java documentation may be erroneous and he points out that you are actually setting the value of foo from inside class A. So everything is correct. You cannot (because it is private) access foo from an descendant, so you must cast. And you cannot do that outside of the body of A.
I believe this is the correct answer.
public class Foo {
public int a = 3;
public void addFive(){
a += 5; System.out.print("f ");
}
}
public class Bar extends Foo {
public int a = 8;
public void addFive(){
this.a += 5;
System.out.print("b " );
}
}
public class Test {
public static void main(String args[]){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I am getting output b 3 .why it is not giving b13 as output.Can anyone please explain.
Assuming class Foo is declared as below
class Foo
{
public int a = 3;
public void addFive()
{
a += 5;
System.out.print("f ");
}
}
Variables have no concept of overriding. They are just masked.
It is printing 3 because, when you use a superclass reference to access a variable, it accesses the variable declared in superclass only. Remember that superclass doesn't know anything about subclass.
class Foo {
public void addFive() {
a += 5; System.out.print("f ");
}
}
you don't have 'a' variable defined, so this example doesn't even compile.
correct code:
class Foo {
public int a;
public void addFive() {
a += 5; System.out.print("f ");
}
}
and see link https://stackoverflow.com/a/2464254/1025312
I assume that you meant to declare an integer field a in class Foo.
The answer to your question has to do with concepts of 'overriding' and 'hiding', as others have pointed out. Another way to explain it is that for member variables, there is no such thing as 'dynamic dispatch'. What that means is that, if you access a member of a certain object, the system checks at run time which member you mean, by looking at the class hierarchy.
So, when calling the method f.addFive, at run time, the system will see that your object is actually a Bar and not a Foo, and so take the addFive function that you defined in the Bar class.
That does not happen for member variables: you access f.a in your print statement, and at compile time it is decided that right there you want to access the field a declared in class Foo there -- and so, that is what will happen at run time.
Now, the reason that there is no dynamic dispatch for member variable access is performance: it would be very expensive to go through the whole 'see what object this really is' logic every time you just want to add some value to a member variable.
Declaring public int a = 8 in Foo class instead of Bar class it should work... printing B 3.
But I suppose you are talking about a question included in the Java certification exam, so you have to correct the code of the Foo class adding public int a = 3.
You cannot override a variable in Java, but declaring in as public (or protected) in the super-class you can use it also in all inherited classes.
In this case the right output is B 13 because in the test class you are using a Bar object as a Foo object, so the value of a is 3 and not 8.
Consider the int a variables in these classes:
class Foo {
public int a = 3;
public void addFive() { a += 5; System.out.print("f "); }
}
class Bar extends Foo {
public int a = 8;
public void addFive() { this.a += 5; System.out.print("b " ); }
}
public class test {
public static void main(String [] args){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I understand that the method addFive() have been overridden in the child class, and in class test when the base class reference referring to child class is used to call the overridden method, the child class version of addFive is called.
But what about the public instance variable a? What happens when both base class and derived class have the same variable?
The output of the above program is
b 3
How does this happen?
There are actually two distinct public instance variables called a.
A Foo object has a Foo.a variable.
A Bar object has both Foo.a and Bar.a variables.
When you run this:
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
the addFive method is updating the Bar.a variable, and then reading the Foo.a variable. To read the Bar.a variable, you would need to do this:
System.out.println(((Bar) f).a);
The technical term for what is happening here is "hiding". Refer to the JLS section 8.3, and section 8.3.3.2 for an example.
Note that hiding also applies to static methods with the same signature.
However instance methods with the same signature are "overridden" not "hidden", and you cannot access the version of a method that is overridden from the outside. (Within the class that overrides a method, the overridden method can be called using super. However, that's the only situation where this is allowed. The reason that accessing overridden methods is generally forbidden is that it would break data abstraction.)
The recommended way to avoid the confusion of (accidental) hiding is to declare your instance variables as private and access them via getter and setter methods. There are lots of other good reasons for using getters and setters too.
It should also be noted that: 1) Exposing public variables (like a) is generally a bad idea, because it leads to weak abstraction, unwanted coupling, and other problems. 2) Intentionally declaring a 2nd public a variable in the child class is a truly awful idea.
From JLS
8.3.3.2 Example: Hiding of Instance Variables This example is similar to
that in the previous section, but uses
instance variables rather than static
variables. The code:
class Point {
int x = 2;
}
class Test extends Point {
double x = 4.7;
void printBoth() {
System.out.println(x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
sample.printBoth();
System.out.println(sample.x + " " +
((Point)sample).x);
}
}
produces the output:
4.7 2
4.7 2
because the declaration of x in class
Test hides the definition of x in
class Point, so class Test does not
inherit the field x from its
superclass Point. It must be noted,
however, that while the field x of
class Point is not inherited by class
Test, it is nevertheless implemented
by instances of class Test. In other
words, every instance of class Test
contains two fields, one of type int
and one of type double. Both fields
bear the name x, but within the
declaration of class Test, the simple
name x always refers to the field
declared within class Test. Code in
instance methods of class Test may
refer to the instance variable x of
class Point as super.x.
Code that uses a field access
expression to access field x will
access the field named x in the class
indicated by the type of reference
expression. Thus, the expression
sample.x accesses a double value, the
instance variable declared in class
Test, because the type of the variable
sample is Test, but the expression
((Point)sample).x accesses an int
value, the instance variable declared
in class Point, because of the cast to
type Point.
In inheritance, a Base class object can refer to an instance of Derived class.
So this is how Foo f = new Bar(); works okay.
Now when f.addFive(); statement gets invoked it actually calls the 'addFive() method of the Derived class instance using the reference variable of the Base class. So ultimately the method of 'Bar' class gets invoked. But as you see the addFive() method of 'Bar' class just prints 'b ' and not the value of 'a'.
The next statement i.e. System.out.println(f.a) is the one that actually prints the value of a which ultimately gets appended to the previous output and so you see the final output as 'b 3'. Here the value of a used is that of 'Foo' class.
Hope this trick execution & coding is clear and you understood how you got the output as 'b 3'.
Here F is of type Foo and f variable is holding Bar object but java runtime gets the f.a from the class Foo.This is because in Java variable names are resolved using the reference type and not the object which it is referring.
Consider this:
class A {
int x =5;
}
class B extends A{
int x =6;
}
public class CovariantTest {
public A getObject() {
return new A();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
}
}
class SubCovariantTest extends CovariantTest {
public B getObject(){
return new B();
}
}
As far as I know, the JVM chooses a method based on the true type of its object. Here the true type is SubCovariantTest, which has defined an overriding method getObject.
The program prints 5, instead of 6. Why?
The method is indeed chosen by the runtime type of the object. What is not chosen by the runtime type is the integer field x. Two copies of x exist for the B object, one for A.x and one for B.x. You are statically choosing the field from A class, as the compile-time type of the object returned by getObject is A. This fact can be verified by adding a method to A and B:
class A {
public String print() {
return "A";
}
}
class B extends A {
public String print() {
return "B";
}
}
and changing the test expression to:
System.out.println(c1.getObject().print());
Unless I'm mistaken, methods are virtual in java by default, so you're overriding the method properly. Fields however (like 'x') are not virtual and can't be overriden. When you declare "int x" in B, you are actually creating a totally new variable.
Polymorphism doesn't go into effect for fields, so when you try and retrieve x on an object casted to type A, you will get 5, if the object is casted to type B, you will get 6.
When fields in super and subclasses have the same names it is referred to as "hiding". Besides the problems mentioned in the question and answer there are other aspects which may give rise to subtle problems:
From http://java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html
Within a class, a field that has the
same name as a field in the superclass
hides the superclass's field, even if
their types are different. Within the
subclass, the field in the superclass
cannot be referenced by its simple
name. Instead, the field must be
accessed through super, which is
covered in the next section. Generally
speaking, we don't recommend hiding
fields as it makes code difficult to
read.
Some compilers will warn against hiding variables