public class PrivateOverride {
private void f() {
System.out.println("private f()");
}
}
public class Derived extends PrivateOverride {
public void f() { //this method is never run.
System.out.println("public f()");
}
}
public static void main(String[] args) {
// instantiate Derived and assign it to
// object po of type PrivateOverride.
PrivateOverride po = new Derived();
// invoke method f of object po. It
// chooses to run the private method of PrivateOveride
// instead of Derived
po.f();
}
}
So, the output of this code is private f(). Now, the question arises to my mind: how can po which is an object of Derived Class call a private method of PrivateOverride which is its base class?
Because you defined the main method in PrivateOverride class. If you put the main method in Derived class, it would not compile, because .f() would not be visible there.
po.f() call in PrivateOverride class is not a polymorphism, because the f() in PrivateOverride class is private, so f() in Derived class is not overriden.
I do not really see the problem. That method is called ""within"" the class, this is pretty much expected.
This method is not overidden at all, instead it is shadowed by another one.
Methods in Java are dispatched depending on the static type of the receiver, which in this case is a PrivateOverride. Do not be confused by the fact that the po variable, by examining the code, can only hold a Derived instance at that line: only the declaration matters when available methods are searched.
And, by the way, the call to f() is not even translated into a virtual call in the final bytecode, because when the compiler looks for the potentially applicable methods in the class PrivateOverride, it only finds Object methods and the f() definition, which is only visible because the main() method is defined in PrivateOverride itself (see JLS 15.12)
I just went through the byte code of the compiled version of the above class and got the invokespecial Opcode. This Opcode was enough to tell the reason why the actual output is obvious. Invokespecial is used in three situations in which an instance method must be invoked based on the type of the reference, not on the class of the object. The three situations are:
1)invocation of instance initialization () methods
2)invocation of private methods
3)invocation of methods using the super keyword
Above example lies within the second scenario where we have invocation of private methods. So the method got invoked based on the the type of reference i.e PrivateOverride rather than type of class i.e Derived
So now the question arises why invokespecial? We have other Opcode like invokevirtual which gets invoked for method on the basis of classtype rather than reference type. So lets discuss why invokespecial Opcode is used for private methods. But we should know the difference between invokevirtual and invokespecial. Invokespecial differs from invokevirtual primarily in that invokespecial selects a method based on the type of the reference rather than the class of the object. In other words, it does static binding instead of dynamic binding. In each of the three situations where invokespecial is used, dynamic binding wouldn't yield the desired result.
When a method is invoked the JVM has to figure out what piece of code to execute: sometimes this is done at runtime (e.g. when overriding methods); sometimes this is done at compile time (e.g. when overloading methods). Once the JVM resolves what bit of code it is executing the actual instance that you are referring to isn't really any more significant than any other parameter.
The example code given sets up a scenario that may look like method overriding but isn't, so the method ends up getting bound at compile time. The private visibility modifier is not violated because the invocation doesn't touch any of Derived's code.
Looking at the bytecode (which the Java code is compiled to via javac) is instructive -
Say we slightly modify the original code to:
public class PrivateOverride {
private void f() {
System.out.println("private f()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
Derived d = new Derived();
d.f();
}
}
class Derived extends PrivateOverride {
public void f() {
System.out.println("public f()");
}
}
The main method compiles to (edited for brevity):
public static main([Ljava/lang/String;)V
NEW Derived
DUP
INVOKESPECIAL Derived.<init>()V
ASTORE 1
ALOAD 1
INVOKESPECIAL PrivateOverride.f()V
NEW Derived
DUP
INVOKESPECIAL Derived.<init>()V
ASTORE 2
ALOAD 2
INVOKEVIRTUAL Derived.f()V
RETURN
Notice that in each case the method is invoked on the compile time type. Notice also that the second call of f() uses the INVOKEVIRTUAL instruction. This is what tells the JVM to check the runtime type and decide what to call based on that.
It behaves this way because that is how the JVM was defined to behave in those cases.
The hard part is understanding what is going on and why.
You invoked the private method from within the class in which it was private. So the trojan horse is inside the castle, he can fiddle with the private variables. Take the trojan horse out of the castle and the private method is no longer visible.
This example might clear things up, Consider this program:
public class Bicycle {
private void getCost() {
System.out.println("200");
}
public static void main(String[] args) {
Bicycle ACME_bike = new ACME_bike();
ACME_bike.getCost();
Bicycle mybike = new Bicycle();
mybike.getCost();
ACME_bike acme_bike = new ACME_bike();
acme_bike.getCost();
//ACME_bike foobar = new Bicycle(); //Syntax error: Type mismatch:
//cannot convert from
//Bicycle to ACME_bike
}
}
class ACME_bike extends Bicycle {
public void getCost(){
System.out.println("700");
}
}
This program prints:
200
200
700
If you change the access modifier of getCost within Bicycle to public, protected, or package private(no modifier), Then it prints this:
700
200
700
There are four visibility levels in Java, package-level (implied by not using any visibility), public (everyone can call this), private (only I, and internal classes that see my functions as global, can call this), and protected (I, and any subclass, can call this).
You can either make your second class an internal class and then you don't override but simply call the function as if it's global (as far as the internal class is concerned), but then you can't really create instances wherever you want because it's a class that can be used exclusively by the owner (so if you want to use it elsewhere, the owner would need to be a factory and return it as if it's the base class) or you can make the method protected, and then the extending class can call the method.
Related
bb refers Derived class, when i call show() method, but when i print bb.b - is prints Base class property .
Why is this happening?
class Base {
int b=10;
public void show() {
System.out.println("Base show() called");
}
}
class Derived extends Base {
int b=20;
public void show() {
System.out.println("Derived show() called");
}
}
public class MainClass {
public static void main(String[] args) {
Base bb = new Derived();;
bb.show();
System.out.println(bb.b);
}
}
output :
Derived show() called
10
While you declare your variable as a Base obj (i.e. Base bb = new Derived();), that does not mean your b object is no longer an instance of Derived (verify this with b instanceof Derived).
This is called hiding and is similar to what people usually do when declaring variables that might later change implementation for example private List<String> someList = new ArrayList<>();. In more technical terms: it's a way of decoupling your code from a specific implementation.
As to why b is 10 (the Base class's value) and not 20: that is because you are explicitly referring to b value in Base class (as mentioned by Timothy Truckle's answer). If you were to explicitly cast your b object back to Derived type, you will see 20 being printed instead:
System.out.println(((Derived)b).b);
You output is 10because you explicitly access variable b in class Base.
Beside the technical aspect doing so this is not OOP since it violates the most important OO principle: information hiding / encapsulation.
This is because the compiler implements special run time polymorphism for methods only. This is also called method overriding.
For variables, the value will always be from the Base class, because that is the type of bb object regardless of the class with with it is instantiated.
There is no polymorphism for fields in Java.
Variables are resolved compile-time, methods run-time. so always Base Class variables (not child’s inherited variables) will be accessed.
So whenever upcasting happens always remember
Base Class variables will be accessed.
Sub Class methods(overridden methods if overriding happened else inherited methods as it is from parent) will be called.
i have just started learning java::Inheritance and confused while mixing Up-Casting.
class Example{
public void methodOne(){
System.out.println("Example::Method_1");
}
public void methodTwo(){
System.out.println("Example::Method_2");
}
}
public class Test extends Example{
public void methodTwo(){ //Method overriding
System.out.println("Test::Method_2");
}
public void methodThree(){
System.out.println("Test::Method_3");
}
public static void main(String[] args){
Example exa = new Test(); // UpCasting
exa.methodOne(); // Printing Example::Method_1
exa.methodTwo(); // Printing Test::Method_2
// exa.methodThree(); // Error : can not find symbol
}
}
may someone please explain, what happening here??
When using inheritance, the compile-time type of the reference to an object on which you call a method is only used to see (at compile time) if the method may be invoked.
But at the invocation time, it does not matter what that compile-time type is. What really matters in this case is the runtime type of the object. It is Test, so the method is searched on Test first.
For methodOne() it is a bit different: it is not overriden by Test, so the version from its superclass (Example) is invoked.
Class Test extends Example and overrides the implementation of the methodTwo while adding new method methodThree. Now in you main
public static void main(String[] args){
Example exa = new Test(); // UpCasting
exa.methodOne(); // Printing Example::Method_1
exa.methodTwo(); // Printing Test::Method_2
// exa.methodThree(); // Error : can not find symbol
}
Static type of the variable exa is Example hence API usage bounded by public methods defined in Example class therefore it's illegal to call exa.methodThree() (not defined it Example).
While for methods which are define at Example class there is a dynamic binding at runtime, which leads to concrete implementation based on the reference pointed by exa variable. Therefore exa.methodTwo() call leads to execution of overrided function, since dynamic type is Test. And since Test doesn't override methodOne calling exa.methodOne() will lead to the implementation defined by Example.
if we create object of subclass and use reference of supper class then runtime time dynamic binding happens means at runtime java decides that which thing should get called.
in your case :
1. exa.methodOne(); methodOne belongs to super class and its not being overridden in child class so parent class method will be executed.
here if you create object like Test test = new Test(); then also test.methodOne() will give you the same result.
exa.methodTwo(); here methodTwo is being overridden in child class so at run time overridden method will get bonded and same will get executed.
in third case its giving error because you are using parent class reference but methodThree() is not part of parent so compile error is being thrown.
if wanna call third method then you can call like this : Test test = new Test(); test.methodThree()
FYI,
for safety we should always use #Override annotation in child call methods if we want to override any parent class method. it will help to avoid any method override glitches.
Given the following block of code i would like to understand why and how, emphasis on how, the method print in Subclass is invoked:
class Super {
Super() {
// what happens so that Sub's method print() is invoked
print();
}
public void print() {
System.out.println("in super");
}
}
class Sub extends Super {
Sub() {
super();
}
public void print() {
System.out.println("in sub");
}
}
public class TestClass {
public static void main(String[] args) {
Super s = new Sub(); // "in sub".. not so much expected
s.print(); // "in sub".. as expected
}
}
My understanding is that during compile time, classes will get V-table pointervtblPtrassociated with methods 'belonging' to a class.
Class Super should therefore have reference to it's own implementation of method print().
How come the method print() in Sub is invoked in constructor of Super? What really happens here ?
Here is what Super class looks like for the JVM (actually, that is the human-readable version obtained by javap -c Super)
class Super {
Super();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: invokevirtual #2 // Method print:()V
8: return
public void print();
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String in super
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
as you can see, the print inside Super contructor was not resolved at compile time to Super::print. A virtual call means that it is resolved at runtime, with respect to class of this.
My understanding is that during compile time, classes will get V-table pointervtblPtrassociated with methods 'belonging' to a class. Class Super should therefore have reference to it's own implementation of method print().
You have a fundamental misunderstanding about virtual methods and overriding. In Java, every non-static, non-private method is virtual. Every virtual (normal) invocation of a virtual method, from anywhere, will invoke the version associated with the class of the object on which the method is invoked. That version might or might not be inherited, and might or might not override a superclass's method.
That a virtual method invocation is performed implicitly or explicitly on this in no way changes any of that. In particular, the actual class of the object being initialized is visible to every constructor, and provides the context for all their method invocations. In fact, this is why it's rarely a good idea for a constructor to invoke a virtual method provided by its own class. Superclass constructors run before subclass constructors, so if a superclass constructor invokes a method that happens to be overridden by a subclass, then that method will run before the object is fully initialized in the way that method may assume.
So I know that in Java when you have a static method you are supposed to call it with the format ClassName.method() rather than use the same structure as you would for instance methods, namely:
ClassName myObject = new ClassName();
myObject.method();
However, if you were to do it this way it would still be valid code and would work. Let's say I decide to do this where the method in question is static, and have the following setup:
public SuperClass {
public static int foo(int x) {
return x;
}
}
public SubClass extends SuperClass {
public static int foo(int x) { // Overriding foo() in SuperClass
return x + 1;
}
}
public MyDriver {
public static void main(String[] args) {
SuperClass myObject = new SubClass(); // Upcasting.
System.out.println(myObject.foo(5)); // This should polymorphically print 6
}
}
What prints out on the screen, however, is 5 rather than 6. Why?
Static methods apply only to the class they are defined in, and they cannot be overridden.
When you call myObject.foo(5), you are calling SuperClass.foo(5) in reality, because you declared myObject as a SuperClass, regardless of whether you instantiated it as one.
The proper way to call a static method is to call it directly from the class it is declared in, so if you wanted to call SubClass.foo(), you must call it from an explicitly declared SubClass instance (meaning no upcasting), or you need to call SubClass.foo() like so.
The simple answer is that calling static methods from instances evaluates to calling those same methods from the declared type with no instance rather than the instance type.
I am not certain of this, but I would not be surprised if when the code is compiled into byte-code, that the instance static method call would actually be compiled into a direct call to the declared type.
Edit: An upvote brought my attention back to this and I cleaned up the explanation to make it more clear and fix some negligible grammatical mistakes on my part. I hope this helps future readers.
Using instances of a class to call that class's static methods is something you should avoid, since it can cause confusion. If you need to call any method polymorphically, make it an instance method. You cannot polymorphically call a static method. The reason the SuperClass invocation is called is because that is the apparent class of myObject at compile-time. This effect can also be seen in the following scenario:
public void doSomething(SuperClass param) {
System.out.println("SuperClass");
}
public void doSomething(SubClass param) {
System.out.println("SubClass");
}
public void test() {
SuperClass myObject = new SubClass();
doSomething(myObject);
}
If test() is called, SuperClass will be printed.
Static methods don't depends on the instance, they belong to the class and only to the class, in fact if you have a static method you'll always access to one unique instance always.
myObject.foo(5)
is only a shortcut, what you really are doing is
SuperClass.foo(5)
Static methods are treated as global by the JVM, they are not bound to an object instance at all. By the way, you can only overload static methods, but you can not override. So check for "Oracle Documentation for Overriding and Hiding Documents".
Defining a Method with the Same Signature as a Superclass's Method:
-----------------------------------------Superclass Instance MethodSuperclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides
I have the following code snippet that attempts to use this and super.
class SuperClass
{
public final int x=10;
public final String s="super";
public String notOverridden()
{
return "Inside super";
}
public String overrriden()
{
return "Inside super";
}
}
final class SubClass extends SuperClass
{
private final int y=15;
private final String s="sub"; //Shadowed member.
#Override
public String overrriden()
{
return "Inside sub";
}
public void test()
{
System.out.println(super.notOverridden());
System.out.println(this.notOverridden());
System.out.println(this.overrriden());
System.out.println(super.overrriden());
System.out.println(this.s);
System.out.println(super.s);
System.out.println(this.x);
System.out.println(super.x);
System.out.println(this.y);
}
}
public final class Test
{
public static void main(String[] args)
{
SubClass subClass=new SubClass();
subClass.test();
}
}
In this simplest of Java code, the statements that redirect the output to the console inside the method test() within the class SubClass display the following output.
Inside super
Inside super
Inside sub
Inside super
sub
super
10
10
15
So, it appears that there is no difference between this and super, when they are used to access methods which are not overridden in its subclass(es) and in case of variables, when they are not shadowed in its subclass(es).
Both of them tend to point to super class members. There is however, an obvious difference, if such is not a case.
Are they same, when methods are not overridden or variables are not shadowed in respective subclasses?
So, it appears that there is no difference between this and super,
when they are used to access methods which are not overridden in
its subclass(es) and in case of variables, when they are not
shadowed in its subclass(es).
There is a difference. If you override methods in third class, and call test from it, you will see, that super still calls implementations of SuperClass. And this will call new implementations (overridden).
Addition:
this.method() usage implies the method belongs to instance of the object. So the last implementation will be used (with exception of private methods).
super.method() usage implies method of the instance, but implemented before the current class (super, or super.super etc).
Yes, they are the same. notOverridden methods and not shadowed variables are inherited by subclass.
To better understand this, knowing how object is located in memory is helpful. For example in the figure below. Assume it's an object of a subclass. The blue area is what it inherits from its parent, and the yellow area is what is defined by itself. The method has the similar design except that it uses a Vtable.
Child object has the same memory layout as parent objects, except that it needs more space to place the newly added fields. The benefit of this layout is that a pointer of parent type pointing at a subclass object still sees the parent object at the beginning.