Why can methods be overridden but variables can't? - java

Code:
public class ClassTest {
public static void main(String args[]) {
test1 cc = new test2();
System.out.println(cc.A);
System.out.println(cc.B);
cc.method1();
cc.method2();
}
}
class test1 {
static int A = 2;
int B = 5;
void method1() {
System.out.println("Inside method 1 test1");
}
static void method2() {
System.out.println("Inside method2 test1");
}
}
class test2 extends test1 {
static int A = 4;
int B = 6;
void method1() {
System.out.println("Inside method 1 test2");
}
static void method2() {
System.out.println("Inside method 2 test2");
}
}
OUTPUT:
2
5
Inside method 1 test2
Inside method2 test1
Question:
Why are only the methods overridden, but the variables remain unchanged?
Does this behaviour have a name? (like "overriding" for methods)

Overriding a method means let the same method call execute another method body (in the child class).
For a variable "overriding" is unnecessary: you can overwrite the variable's value.
Declaring a variable in the child class with the same name hides the parent classes variable and introduces an additional field.
For methods to be overridable a special mechanism is needed so that the place in the code may call the method that the actual class of the object specifies. This as opposed to accessing a field.

What happened here was that you've used type1 reference to point to an instance of test2. You can do this because test2 is a type of test1 - this is called Polymorphism.
test2 is derived from test1, so when you create an object of type test2 you will basically have two objects created, test2 and test1 (which will not reside in the heap as an autonomous object).
The JVM will access the fields of the object from its reference (because Java is a statically typed language).
So, although, test2 hides both fields of test1, when trying to access them from the test1 reference Java goes automatically to test1.
That's about it regarding the fields.
When dealing with methods we have a more complicated issue. Methods are overridden, thus, when the method table is built, the methods of test2 override the methods of test1. But, static methods are not instance methods.
Thus, when trying to access the static method method2, of test2 from the reference of test1, you are "abusing" the code. What you should be doning is calling test1.method2() or, if you want to access the static method of test2 you should use test2.method2().
Hope I explained it well enough...

In Above example you are creating reference of base class that time it will take value A=2,B=5 and it will allocate memory also.so when override to derived class, base class variable hide the derived class variable values that's why it can not override in derived class.

In line: System.out.println(cc.A);
This is not the correct way for calling static member, you should always use class name, eg: System.out.println(test1.A);
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
Whether the variable be static or nonstatic. Only methods can be overriden.
That's why the output of cc.A & cc.B is from test1 class
For Method Overriding:
The code cc.method1(); here overrriding takes place, the object type(i.e the instance of class) actually determines which method is selected at run time, by this object declaration of new test2() in this code: test1 cc = new test2();
The compiler first checks the method in test1 class and then it checks in method in text2 class, if all the signatures (arguments, return types etc) are same then it invokes the sub class method
since it is overriding the base class method, because actual object is of class test2.
For Static methods:
Static methods cannot be overridden because method overriding only occurs in the context of dynamic (i.e. runtime) lookup of methods.
Static methods (by their name) are looked up statically (i.e. at compile-time).
thats why the output is from class test1.
For "static methods" in Java the exact method to call is determined at compile time.
You explicitly specify the name of the class whose static method you want to execute

Related

Java output explanation [duplicate]

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.

Why can't I refer enclosing class's non-static var from its inner class's non-static method?

In my awareness, non-static method will be assigned "this" variables for its class obj & all enclosing classes.
public class TestNested {
int a=4;
public static class a{
int a=5;
static int c=10;
class b{
int a=6;
void aaa(){
int a=7;
TestNested t=new TestNested();
System.out.println(this.a);
System.out.println(b.this.a);
System.out.println(TestNested.a.b.this.a);
System.out.println(TestNested.a.this.a);
System.out.println(a.this.a);
System.out.println(t.a);
System.out.println(TestNested.this.a);
}
}
}
void r(){
TestNested t=new TestNested();
TestNested.a a=new TestNested.a();
a.b b=a.new b();
b.aaa();
}
public static void main(String[] args) {
TestNested t=new TestNested();
t.r();
}
}
in this case the final statement of void aaa() is System.out.println(TestNested.this.a); will be sentenced to cause compilation error with the reason :'com.xxx.TestNested.this' cannot be referenced from static context, that's really confusing me because the this var that points to TestNested should be the non-static hidden var of the method itself,then why it can't use its own var?
Or if my awareness is wrong that each that var is assigned in each class enclosed from the method's class, but the void aaa() isn't a static method which means it can reference non-static var rite? or even the method isn't static, but if one of its enclosing class is static, it'll be automatically recognized as static member?
This is because your nested class a is not an inner class of TestNested. It is a static nested class, meaning that it is not linked to a particular instance of TestNested.
Note: an inner class is a non-static nested class.
What instance of TestNested would you expect your expression TestNested.this to refer to?
You can see, by the way, that you're not referring to your variable t here:
TestNested.a a=new TestNested.a();
Which points out that the object a is not linked to t at all.
In my above answer, I assumed it was clear to you what you were doing with this. It appears it is not the case, according to your comments, so I'm going to try and clarify it here.
First of all, this always refers to an object: an instance of a class.
Let's assume we're in the context of a non-static method in the class b. Because the method is non-static, the code will be executed relatively to a particular instance of b. I take the shortcut to refer to this particular instance as "the instance of b you're in".
Since b is an inner class of a, no instance of b can exist outside an instance of a. This means the instance of b you're in is enclosed in an instance of a. I take the shortcut to refer to this particular instance as "the instance of a you're in" (Technically, you're in a b which is in an a).
So, in this context of a non-static method of b:
this refers to the instance of the b you're in. It is the standard use of this keyword.
b.this, a.b.this or TestNested.a.b.this are the same as this here, the difference is only that you qualify more precisely the class b.
a.this or TestNested.a.this both refer to the instance of a you're in (TestNested.a is just a more precise qualification for a). This a object exists because b is an inner class of a, which means that every instance of b is linked to an instance of a. This is the only way to refer to the instance of a.
TestNested.this would refer to the instance of TestNested you're in. But you're not in any instance of TestNested, so it does not mean anything, hence the compile error. You're in an instance of b, which is within an instance of a (because b is an inner class of a). The instance of a exists by itself because a is a static nested class of TestNested, so it is not linked to an instance of TestNested.
TestNested.a <-- references a static variable of a static class
this.a <-- references an instance variable of an object
TestNested.this <-- tries to reference an object from a static context, but "this" does not exist in a static context.
You can reference static content from non-static, but not vice-versa.

Creating objects of a subclass as instances of the superclass in Java

say, I have the following code (it's a quiz question, so I can run it in my IDE but the logic how it's working is not quite clear to me):
public class Test {
public static void main(String[] args){
A aInstance1 = new A();
A aInstance2 = new B();
A aInstance3 = new C();
aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();
}
}
class A {
public static void doSth(){
System.out.println("Doing something in A");
}
}
class B extends A {
public static void doSth(){
System.out.println("Doing something in B");
}
}
class C extends B {
public static void doSth(){
System.out.println("Doing something in C");
}
}
The output will be the following:
Doing something in A
Doing something in A
Doing something in A
Thus, my first question is: what is the meaning of the declaration like
A aInstance2 = new B();
i.e., why to create an object of class B declaring it as an instance of class A? How the properties of aInstance2 as an object of class B change compared to the declaration
B aInstance2 = new B();
?
If I remove the word static from the declaration of the methods doSth() in the classes A, B, and C, the output changes to
Doing something in A
Doing something in B
Doing something in C
Thus, when the methods were static, the method doSth() of class A didn't get overridden by those of the subclasses and the output was always "Doing something in A" produced by the objects of different classes, whereas when it became an instance (non-static) method, it gets overridden (if I'm using the right term here). Why is it so?
Removing the word static you are doing Dynamic Binding , because you are pretty much saying : "Even though i know this object is of type A i want it to behave like a B ".
Adding the word static means you are making that method part of the class[Reference type] ,and each time you are calling :"A dosmth()" he knows it only applies to A so it shows the result of the mothod from the class A.
As to what would you do this?I for one learned about this feature from school and studied it even more when i decided to go to interviews becuase it;s one of the things that the interviewer wants to see if you can handle.
If you don't mind I will post a link with information about Static and Dynamic Binding
http://javarevisited.blogspot.ro/2012/03/what-is-static-and-dynamic-binding-in.html
Because static method is based on Reference type .
aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();
So internally it converts into :
A.doSth();
A.doSth();
A.doSth();
Static methods are class methods while non-static ones are instance methods. Therefore, when you call a static method over an instance you are actually calling it over the declared type of this instance. So, all below calls actually performs the same call: A.doSth() since all instances are declared as type A.
aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();
When you remove the static keyword, doSth() method becomes an instance method. Instance methods are performed over objects instead of classes. Moreover, when you re-declare an instance method in a subclass, this method is overriden by the subclass. In your example, class B and C override doSth(). Thus, each class provides its own implementation.
Overriding depends on having an instance of a class. A static method is not associated with any instance of a class so the concept is not applicable.
Making static methods works faster, because there's no need to wait until run-time to figure out which method to call.
Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it.
Illustration -
When doSth() is static:
A aInstance1 = new A();
A aInstance2 = new B();
A aInstance3 = new C();
aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();
In the above code, the compiler will decide at compile time that without instance it should be called for A. No overriding.
When doSth() is not static:
A aInstance1 = new A();
A aInstance2 = new B();
A aInstance3 = new C();
aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();
In the above code, the compiler will decide at run time that the method is not static and should be overridden by there respective instances.
static methods are at class level and act on the reference type(LHS of ==) unlike instance level methods which are dynamically dispatched based on the instance type(RHS of ==)

How to declare a method with arrays in main?

I wrote this in my main because I want to call this method bla_methods from my main.
I wrote an method called bla_methods already. The main isn't letting me call my bla_method.
Sorry, I should have clarified myself. But, thanks everyone!
bla_methods (one_data[], two_datas[], length);
then I get this error for one_data[] and two_datas[]
<<gradeabc.java:45: error: '.class' expected >>
You declare methods within your class, but outside of other methods (unless it's a method in an inner class)...
public static void bla_methods (String[] one_data, int[] two_datas, int length) {
// do something.
}
public static void main(String[] args) {
// ...
}
Should work.
No, Java doesn't allow you to define methods inside of other methods - main included.
Just put the method inside the same class as main.
You didn't specified the data type of the array, that's why you got the error.
private static void bla_methods (DATA_TYPE[] one_data, DATA_TYPE[] two_data, int length){
//your code
}
public static void main(String[] args){
bla_methods(a, b, c);
//
}
the "DATA_TYPE" int bla_method can be any data type. such as int, float etc. it can also be an Object of a class, such String...
Methods cannot be nested.
You can only create a method directly inside a class.
You have to understand a few things to be able to work in Java:
Everything, methods and members are parts of either a class or an object. By inside I mean they are inside their block, marked by {}.
A class is declared by the class keyword followed by the name of the class. Example: class foo {/*...*/}
An object is an instance of a class, which is usually instantiated by the new keyword. Example Foo bar = new Foo();
Members can be members of an object or a class (if they are static). They have a type and they might have an initial value. Example: Foo bar = new Foo();
Methods can be methods of an object or a class (if they are static). Methods have a return type, a parameter list and a block of their own, where the exact receipt/algorithm of the method is defined. Example: static public void main(String args[]){/*...*/}
Members represent the state of the object/class where they are applicable.
Methods represent the ability of the object/class where they are applicable.
A parameter is inside the brackets of a method, they have a type as well. Example: public static void main(String args[]){/*...*/}
A variable behaves almost like a member, but it is defined inside a method and is applicable only there.
I think you should read a tutorial, for example this one.
So, you did not associate a type to your variables/parameters and I doubt that your method was defined correctly.

Java Static Method Calling

is Calling a static Java method ( a factory class method ) creates an object of that Class ?
I mean a static method returns a value let's say an Array's size ( array is variable of class )
I've checked the code but couldn't see that the Object of that class never instantiated before calling the static method. ?
public static boolean isFiveInstance() {
return _instances.size() == 5;
}
and _instances is class variable
private static ArrayList<LocalMediaPlayer> _instances;
and is being created and filled in the constructer.
No it does not. That is the point behind creating static methods. Static methods use no instance variables of any object of the class they are defined in either, so everything you refer to inside your static method must be static also.
That is why you call a static method like Class.StaticMethod() instead of:
new Class().StaticMethod();
the new will instantiate that class, thus creating a new instance of that object.
No, static invocations do not instantiated objects (because they do not require one).
The first time you refer to a class, including static method invocation, the class is loaded. by the classloader.
That's where the static initializer comes into play:
static {
// do something
}
this block is called whenever the class is initialized (once per classloader)
No, calling a static method does not create an instance of the class. That's where static methods differ from instance methods. They don't need an instance of the class they belong to to be instantiated to be run.

Categories

Resources