File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Overriding Private Methods Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Overriding Private Methods" Watch "Overriding Private Methods" New topic
Author

Overriding Private Methods

Suresh Chidambaram
Greenhorn

Joined: Aug 05, 2000
Posts: 20
Excerpt from absolutejava.com< !-- BEGIN QUESTION 4 -->
<DIV CLASS="heading">Question 4:</DIV>
Determine the result of attempting to compile and run the following code:
<PRE>
public class Tester {
public static void main(String[] args) {
System.out.println(new Sub().g());
}
private int f() {
return 2;
}
int g() {
return f();
}
}
class Sub extends Tester {
public int f() {
return 1;
}
}
</PRE>

The answer is it prints two.
But I thought the compiler should scream if you try to define a method in the subclass with the same arguments( essentially meaning we are trying to override) and reduce access visibility.
BTW, i have run in 1.1.8 and as stated, it prints 2 faithfully.
Any explanations?/
Thanks

Romba Chinna Thambi
rkapoor
Greenhorn

Joined: Aug 05, 2000
Posts: 2
In the main class int f() is a private method while in subclass int f() is a public method, with overall visibility of sub class, its visibility is more than what it is in the main class. Therefore it should compile and run. Why are you saying that its visibility is reduced?
thomas
Ranch Hand

Joined: May 26, 2002
Posts: 79
First of all, I agree with rkapoor. There is no compiler error since the accessibility modifier of super class method is private and that of the subclass method is public. Had it been the other way around, the compiler would have screamed.
Secondly, I think you touched upon a very tricky situation here. The super class method f() is private. Your subclass has a method with the same signature, but it is actually NOT overriding the super class method since private super class methods CANNOT be overridden. In fact here the subclass method simply shadows the super class method. So when the inherited method g() is called, it in turn calls the super class method f()!
If you change the accessibility of f() from private to protected, default or public, the usual overriding will take place and the code will print 1.
Deepak M
Ranch Hand

Joined: Jul 10, 2000
Posts: 124
>>In fact here the subclass method simply shadows the super class method.
THe subclass method DOES NOT shadow the super class method.
A method can shadow other method only if it comes within its scope.
Here the scope of private f() is limited only to the super class.
HEre's an example of shadowing a method :
class Outer {
void f() {}
class Inner {
void f() {} // shadows Outer.f()
}
}
Check out this example :
class Tester {
public static void main(String[] args) {
System.out.println(new Sub().g()); }
int g() { return f(); }}
class Sub extends Tester {
public int f() { return 1; }
}

Can u explain why the above code does not compile ?
vidya
Ranch Hand

Joined: Aug 08, 2000
Posts: 47
class Tester {
public static void main(String[] args) {
System.out.println(new Sub().g()); }
int g() { return f(); }}
class Sub extends Tester {
public int f() { return 1; }
}
I think this is why the above code does not compile.
When Sub().g() is evoked, since there is no such method in the subclass Sub, the call gets passed up the next higher level, and the method is found in the main class Tester.Again inside the method, a call to method f() is made, and the compiler must say that the method is not found in the class Tester.
I think this is the correct explanation..feel free to correct me...
regards,
vidya.
Satish Varanasi
Ranch Hand

Joined: Aug 13, 2000
Posts: 47
Originally posted by vidya:
[B]class Tester {
public static void main(String[] args) {
System.out.println(new Sub().g()); }
int g() { return f(); }}
class Sub extends Tester {
public int f() { return 1; }
}
Well in my opinion the call to Sub().g() makes the compiler to check g() method in the Sub class and finds it(since it's inherited) , so no problem.
but the call to f() method is not associated with any refernce so the compiler checks for the method in Tester class which it does not find ,there is no way for the compiler to know that there is f() method present in Sub class ,so it shows .
if a reference of Sub class invokes the f() method or if there is a superclass of Tester implementing f() method then the compiler can be made to stop screaming.
please do comment to correct me if i am not Right!
satish varanasi

[This message has been edited by Satish Varanasi (edited August 13, 2000).]
Sanjeet Karamchandani
Ranch Hand

Joined: Jul 29, 2000
Posts: 30
Hi,
here r two questions :
can private methods be overridden : No
Because private methods r implicitly final so they can't be overridden.
Are private methods inherited : No
This is as per Java Language specification. When a method is declared as private, it is not available to any other class, ie it is not inherited. So if its not inheried it cannot be overridden.
public class Tester {
public static void main(String[] args) {
System.out.println(new Sub().g());
}
private int f() { return 2; }
int g() { return f(); }
}
class Sub extends Tester {
public int f() { return 1; }
}
In this case sub().g() is called, but sub has no g() method of its own. but it extends Tester, so it gets g() from superclass, right? but after this im also a bit confused.
Can anyone explain after that?
Thanks
Sanjeet
Originally posted by Satish Varanasi:
Originally posted by vidya:
[B]class Tester {
public static void main(String[] args) {
System.out.println(new Sub().g()); }
int g() { return f(); }}
class Sub extends Tester {
public int f() { return 1; }
}
Well in my opinion the call to Sub().g() makes the compiler to check g() method in the Sub class and finds it(since it's inherited) , so no problem.
but the call to f() method is not associated with any refernce so the compiler checks for the method in Tester class which it does not find ,there is no way for the compiler to know that there is f() method present in Sub class ,so it shows .
if a reference of Sub class invokes the f() method or if there is a superclass of Tester implementing f() method then the compiler can be made to stop screaming.
please do comment to correct me if i am not Right!
satish varanasi
[This message has been edited by Satish Varanasi (edited August 13, 2000).]

vidya
Ranch Hand

Joined: Aug 08, 2000
Posts: 47
Yes, I agree with Satish Varanasi. Had there been a method f() in the superclass of tester, it would have been invoked. But in this case, since the class Tester doesnt seem to extend anything, the compiler must give an error.
Now, I got all messed up with the code posted by Sanjeet:
This is it:
1. public class Tester {
2. public static void main(String[] args) {
3. System.out.println(new Sub().g());
4. }
5. private int f() { return 2; }
6. int g() { return f(); }
7. }
8. class Sub extends Tester {
9. public int f() { return 1; }
10.}
Sanjeet,
I thought the code wont compile,but to my surprise, I found that it compiles perfectly well. This is my explanation ,but I got confused at the end.
Sub().g() will invoke the method g() in the class Tester.
Inside g(),as a response to the statement return f();
the private method f() (in line 5) will be invoked.
This is legal because here, new Sub()(in line 3) is actually
creating a reference to the class Tester.Since a private method can be invoked only by an instance of the class to which it belongs,the method f() in the class Tester is invoked.
then, I tried declaring so: (note line 3)
1. public class Tester {
2. public static void main(String[] args) {
3. Sub ii = new Sub();
4. System.out.println(ii.g());
5. }
6. private int f() { return 2; }
7. int g() { return f(); }
8. }
9. class Sub extends Tester {
10.public int f() { return 1; }
11.}
Here too, the code compiles perfectly well..
ii is an instance of Sub, which invokes g() in the superclass, which in turn invokes the private method f() in the superclass (which can be invoked by only an instance of the class to which it belongs ).
what do I gather from this? Because Sub 'is a' Tester , a reference to Sub (ii here) is able to access a private method in its Superclass??? But this is not what the definition for "private" says....
what am I missing?
waiting for the reply,
regards,
Vidya.
Jayakumar Thirumalai
Greenhorn

Joined: Jul 08, 2000
Posts: 15
As per Java2 Certification Study Guide Page 79:
The rules for overriding can be summarized as follows:
- A private method may be overridden by a private, friendly, protected or public method.
- A friendly method may be overridden by a friendly, protected,or public method.
- A protected method may be overridden by a protected or public method.
- A public method may only be overridden by a public method.

Jayakumar Thirumalai
Jayakumar Thirumalai
Greenhorn

Joined: Jul 08, 2000
Posts: 15
Try with "'public int f()' instead of 'private int f()'".
1. public class Tester {
2. public static void main(String[] args) {
3. System.out.println(new Sub().g());
4. }
5. public int f() { return 2; }
6. int g() { return f(); }
7. }
8. class Sub extends Tester {
9. public int f() { return 1; }
10.}
The result is "1".
Reason - f() in Sub overrides f() in Tester().
When f() in Tester was private,
g() can execute f() in Tester because g() is a method in Tester. Any method in Tester can access private variables and methods.
Eventhough g() has access to both f() in Tester and f() in Sub, it prefers (???) to execute its own private f() method rather than public f() method in Sub.
is this more confusing !!!

Ken Lai
Ranch Hand

Joined: Aug 06, 2000
Posts: 30
Can any JLS experts (I know I'm not ) tell us something about this?
This is tricky because even though f() is private the code was able to call it through the inherited g() method. Is there a valid reason for this?
Thanks.
[This message has been edited by Ken Lai (edited August 13, 2000).]
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
1. public class Tester {
2. public static void main(String[] args) {
3. System.out.println(new Sub().g());
4. }
5. private int f() { return 2; }
6. int g() { return f(); }
7. }
8. class Sub extends Tester {
9. public int f() { return 1; }
10.}
when a new sub().g() is called ,first the JVM checks for the method definition for g() on the called Object which is Sub,its not present in the class definition for Sub ,so it has to traverse up the heirachy where it will find a method
int g() { return f() ; }

the above method defintion is translated by compiler as
int g() { return this.f() }
now the Owner of method g() is Tester ,
But BY virtue of inheritance this method is accessible by Childrens of Tester also.
when the Body says this.f(),the method that is to be executed should be choosen from the same class in which the g() is defined.
Hence the f() in the parent class Tester will be Executed .
on the Otherhand if the g() was overriden and f() was also defined [note if f() will not be defined then surely compiler error will occur] in SUB then f() in SUB will be Accessed.
1. public class Tester {
2. public static void main(String[] args) {
3. System.out.println(new Sub().g());
4. }
5. private int f() { return 2; }
6. int g() { return f(); }
7. }
8. class Sub extends Tester {
9. public int f() { return 1; }
10 int g() { return f(); }
11.}

Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
hello !
1) in the above problem the method int g() is inherited by class class Sub.so there is no problem in printing 2 as output.
2) method private int (){return 2;} is not overridden becuse java does not allow to override a private method.
3)in java there is no word like shadowing.even if a method in inner class has same signature as that of outer class the method is not overridden. it is simply a local method like a local variable and any local member has higher priority than outer one.
4) in the above problem if we define method int g(){return f();}
as a private it will give a compiler error.
5)in the above problem if we define method private int f(){return 2;}as a protected it will give a output 1.
please write me if any one has any other idea.
Satish Varanasi
Ranch Hand

Joined: Aug 13, 2000
Posts: 47
hi folks,
1. public class Tester {
2. public static void main(String[] args) {
3. System.out.println(new Sub().g());
4. }
5. private int f() { return 2; }
6. int g() { return f(); }
7. }
8. class Sub extends Tester {
9. public int f() { return 1; }
10.}
I overlooked line 5 in my prevoius reply:my apology.
I think i have an explanation to offer.As the question is from absolute java,the explanation offerred by them : for private & static methods the compiler does not generate code for run time binding because they cannot be overriden,so they are resolved at compile time ,Hence no question of DynamicMethod lookup.i feel iam clear
Try with static modifier for f() in both classes,
any other view!!!
satish varanasi
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
I agree with Satish. Static methods, private methods, and final methods are statically bound; that is, they're resolved at compile-time. Therefore, the type of the reference variable (not the type of the actual object) determines which version to use.
The thing that is confusing here is that when the object is created in "System.out.println(new Sub().g());" it isn't being assigned to a visable reference variable. If we saw, either "Tester t1 = new Sub(); t1.g();" or "Sub s1 = new Sub(); s1.g();" it might be easier to see what's going on (given the rules listed in my first paragraph).
Don
[This message has been edited by DaB (edited August 14, 2000).]
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Yes satish is correct the private methods are resolved at compile time itself.So No probs in accessing the f() of parent class Tester.
svr
Greenhorn

Joined: Jan 06, 2004
Posts: 8
Hello All,

Here's an explanation. I guess, it fits.
When a Base class has a method as Private its not available for overriding/inheritance. Also, private and static components are resolved/bound at Compile time. Another important point is : If a method in a class calls another member method the default is object "this".
Looking at Tester class, when compiler comes across new Sub().g(), compiler looks for method g() in Sub. This lookup fails and hence compiler looks in higher up at super class Tester, where it finds g(). when it tries to look for f(). Since f() is private in Tester it cannot be overridden/inherited. So any reference to f() from Tester::g() is bind-ed to Tester::f().
That should explain why it prints "2".
When you declare Tester::f() not as private i.e. either protected, default or public you open it (or it available) for overriding and inherting by Sub classes. At compile time now when the compiler comes across this more open declareation it leaves the method call for Late binding (dynamic reference) and hence the Sub::f()overides it and displays '1".
Do I sound confusing ? Is the explanation wrong ? Correct Me
Anytime,
SVR.
svr_76@yahoo.com
svr_76@hotmail.com
anuragbhalla
Greenhorn

Joined: Aug 01, 2000
Posts: 16

So does that imply thet what is written on page 79 of RHE
is wrong.It clearly states :
- A private method may be overridden by a private, friendly,
protected or public method.

Anurag
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Yeah, you can't really trust RHE for accuracy on the fine points. William Brogden or Mughal & Rasmussen would have fixed this by now, at least in their online errata. I guess RHE figure that since they know this particular point won't come up on the exam, it doesn't matter if it's right or not. RHE are fine for passing the exam, but not for learning Java in general, IMO.


"I'm not back." - Bill Harding, Twister
vidya
Ranch Hand

Joined: Aug 08, 2000
Posts: 47
Another observation:

public class Tester {
public static void main(String[] args) {
Sub ii = new Sub();
System.out.println(ii.g());
}
private int f() { return 2; }
int g() { return f(); }
}
class Sub extends Tester {
public int f() { return 1; }
}

Yikes!! RHE may be wrong for the above code,
but is right on the code below:
The code below returns 1 ,which means a private method is overridden by a public method.
Where is this taking me???

public class Tester {
public static void main(String[] args) {
Sub ii = new Sub();
System.out.println(ii.g());
}
private int f() { return 2; }
//int g() { return f(); }
}
class Sub extends Tester {
public int f() { return 1; }
int g() { return f(); }
}

regards,
Vidya.
thomas
Ranch Hand

Joined: May 26, 2002
Posts: 79
No, Vidya. Here, the private super class method is NOT overridden by the sub class method. The sub class method is just another method which happen to have the same signature as the super class method. They are not related.
Also, thanks Deepak for pointing out my incorrect usage of the term 'shadows'.
svr
Greenhorn

Joined: Jan 06, 2004
Posts: 8
Hi All,
Here's a statement from the Sun's JAVA LANGUAGE SPECIFICATION PDF. Who's more Authentic that 'The Father'. Its say :
<Quote>
6.6.8 Example: private Fields, Methods, and Constructors
A private class member or constructor is accessible only
within the class body in which the member is declared and
is not inherited by subclasses. In the example:

class Point {
Point() { setMasterID(); }
int x, y;
private int ID;
private static int masterID = 0;
private void setMasterID() { ID = masterID++; }
}
The private members ID, masterID, and setMasterID may be
used only within the body of class Point. They may not be
accessed by qualified names, field access expressions, or
method invocation expressions outside the body of the
declaration of Point.
<UnQuote>
So that means Private members are not inherited/overridden. Derived class can have a method with the same signature as the Base class private method, But this method will not override the
Base class method.
Its getting 2 much Confusing !
Lets Keep learning,
-SvR
svr_76@yahoo.com
svr_76@hotmail.com
Sanjeet Karamchandani
Ranch Hand

Joined: Jul 29, 2000
Posts: 30
Hi,
Referring to Vidya,
Excuse ME but the answer printed by ur code is 2. Try again.
This is the code :
public class Tester {
public static void main(String[] args) {
Sub ii = new Sub();
System.out.println(ii.g());
}
private int f() { return 2; }
int g() { return f(); }
}
class Sub extends Tester {
public int f() { return 1; }
}
Well as far as i know is private methods cannot be overridden. I agree with svr. I think its because of a internal reference(secret reference as called by Bruce Eckel) passing. I think the program flows as follows
when sub().g() is called a object of sub is created and g() is called for it. but g() is not available in sub so the compilier looks for the method in its superclass(Tester) it finds g() there.
now g() calls f(), note there is no reference while calling with f() so it can be said as this.f(). Now since f() is private the compiler doesn't go to see whether its overridden(coz it can't be overridden) so it executes the superclass version of f().
I hope its clear and more importantly correct.
If anything wrong, let me know
Thanks
Sanjeet
vidya
Ranch Hand

Joined: Aug 08, 2000
Posts: 47
Well..let me ask you this basic question.
vidya
Ranch Hand

Joined: Aug 08, 2000
Posts: 47
Sorry abt that..I accidentally sent it...
Let me just ask this ......

Let me quote Thomas ."The sub class method is just another method which happen to have the same signature as the super class method."
Isn't this what we call overriding? Or am I missing something?
I think I should go by what the JLS says, but unfortunately I am not getting convinced. ( Once again, please refer to the second code attached in my earlier posting)

Referring to Sanjeet,
You are absolutely right regarding the code you used. But that's not the code I was talking about in my earlier posting. I was referring to the second code attached, where I said the code returns 1. You might want to please try that.
regards,
Vidya


Sanjeet Karamchandani
Ranch Hand

Joined: Jul 29, 2000
Posts: 30
Hi Vidya,
Well, i would like to clear it.

Quoted by Thomas ."The sub class method is just another method which happen to have the same signature as the super class method."
I think here he is talking abt a private method in superclass and a method in subclass with the same signature.
EX :
class A {
private void amethod() { }
}
class B extends A {
public void amethod() { }
}
Here u can't say that amethod is overridden coz its private, but the subclass has a method with the same signature, isn't it? So this is not overridding
Now abt ur code :
public class Tester {
public static void main(String[] args) {
Sub ii = new Sub();
System.out.println(ii.g());
}
private int f() { return 2; }
//int g() { return f(); }
}
class Sub extends Tester {
public int f() { return 1; }
int g() { return f(); }
}
In this case it should print one. Well here u r calling the method g() thatz in subclass which in turn calls f()( which could be written as this.f() ) so the compiler searches it first in subclass and finds the method defination in subclass itself and uses it, isn't it straight forward?
Thanks
Sanjeet
svr
Greenhorn

Joined: Jan 06, 2004
Posts: 8
Hi EveryBody,

Are we all on the same page ? Private Methods cannot be Overidden/inherited. Private access modifier restricts that members access to other members within the scope of the same Class. So derived class does not has access to it.

Time to change the name of this Thread !!!
:-)
SvR.
vidya
Ranch Hand

Joined: Aug 08, 2000
Posts: 47
Hi!
I think I am getting it now....Thanks friends, for your time,
especially Sanjeet and Thomas.
regards,
Vidya.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Overriding Private Methods