I know I can use reflection to invoke a private method, and to get or set the value of a private variable, but I want to override a method.
public class Supe
You can't override a private method.
An overriding method can only exist in a subclass of the overridden method. If the method that you want to override is marked private, overriding it is not possible because the subclass doesn't inherit anything marked private, thus severing ties between that private method and anything in the subclass, including any of the subclass's methods.
To "override" means allowing the JVM to determine which method to use based on the instance type that you are invoking it with. The theory of polymorphism explains what makes this possible. In order for the JVM to be able to say "these methods are connected, one overrides the other", the JVM must be able to view the overridden method from within the subclass that contains the overriding method.
That being said, the classes in the case you provided will still compile, but neither of the methods will be invoked based on the JVMs independently run instance-based invocation. They will merely be different methods altogether that fail to be recognized by the JVM as overridden or overriding.
Furthermore, if you are using an IDE such as NetBeans, using the @Override annotation will instruct the compiler that you are overriding the method with the same signature in the superclass. If you don't do this, you will get a warning suggesting that you make the annotation. You will get a compilation error, however, if you apply this annotation when:
OR
Refer to the official Oracle documentation https://docs.oracle.com/javase/tutorial/java/IandI/override.html for the following excerpt:
Instance Methods
...The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed.... When overriding a method, you might want to use the @Override annotation that instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, then it will generate an error.
Overriding can be very confusing because it involves the JVM taking action seemingly independently. Just remember that without access to the method[s] in the superclass (in other words, for all methods marked private), the subclass can't invoke or override the said method[s] because it can't inherit them to do so.
No we cannot override Private methods, but there is a case where we can override private methods too i.e. Inner class
class PrivateTest {
private String msg = "OuterAndInner";
private void fun() {
System.out.println("Outer fun()");
}
class Inner extends PrivateTest {
private void fun() {
System.out.println("Accessing Private Member of Outer: " + msg);
}
}
public static void main(String args[]) {
PrivateTest o = new PrivateTest();
Inner i = o.new Inner();
i.fun();
// o.fun() calls Outer's fun (No run-time polymorphism).
o = i;
o.fun();
}
}
You can't override a private method because no other class, including a derived class, can tell that it exists. It's private.
Private methods are implicitly final
.
On a related note, a subclass can declare a field or method with the same name as a private
field or method in a super class, because from the subclass's point of view, these members do not exist. There's no special relationship between these members.
Private methods are not inherited and cannot be overridden in any way. Whoever told you you can do it with reflection was either lying or talking about something else.
However, you can access the private method getInt
of whatever subclass is invoking printInt
like so:
public void printInt() throws Exception {
Class<? extends SuperClass> clazz = getClass();
System.out.println("I am " + clazz + ". The int is " +
clazz.getMethod("getInt").invoke(this) );
}
This will have the effect of the subclass' getInt
method being called from the superclass' printInt
.
Of course, now this will fail if the subclass doesn't declare a getInt
, so you have to add a check to be able to handle "normal" subclasses that don't try to "override" a private method:
public void printInt() throws Exception {
Class<? extends SuperClass> clazz = getClass();
// Use superclass method by default
Method theGetInt = SuperClass.class.getDeclaredMethod("getInt");
// Look for a subclass method
Class<?> classWithGetInt = clazz;
OUTER: while( classWithGetInt != SuperClass.class ){
for( Method method : classWithGetInt.getDeclaredMethods() )
if( method.getName().equals("getInt") && method.getParameterTypes().length == 0 ){
theGetInt = method;
break OUTER;
}
// Check superclass if not found
classWithGetInt = classWithGetInt.getSuperclass();
}
System.out.println("I am " + classWithGetInt + ". The int is " + theGetInt.invoke(this) );
}
You still have to change superclass code to make this work, and since you have to change superclass code, you should just change the access modifier on getInt
to protected
instead of doing reflection hack-arounds.