Consider the following outline of code:
class B {
int a = 0;
void method1() {
// code
a = a + 1;
}
}
public class A extends Thread {
static B obj1;
public void run(){
obj1.method1();
}
public static void main(String args[]){
obj1 = new B();
A a1 = new A();
a1.start();
A a2 = new A();
a2.start();
}
}
Now, since a1 and a2 are two different objects, shouldn't the value be 1 while printing the value of a?
What am I missing?
How is the global reference for B working? I'm a little confused.
This code should produce compilation error.
How is the global reference for B working?
It doesn't. obj1 (type class B) is a non-static member of class A. The main method is static and not really running in context of any class A object. For this reason, the main function (static function) cannot access obj1 directly.
obj1 = new B();
In the above line, there is no actual memory of obj1 to store the reference created by new B(). Two different memory for obj1 are created as part of a1 and a2, which need to accessed as a1.obj1 and a2.obj2. Thus, no kind of global reference is created.
What you might be trying to do can be achieved by making obj1 as static.
static B obj1;
This can make obj1 act as a global reference as its memory is not part of any class A object. This will make both threads update same variable making value of obj1.a as 2 (not necessarily as the code isn't thread-safe).
Related
Deitel's How To Program Java book says:
A final field should also be declared static if it is initialized in its declaration to a value.
Why is that?
public class A
{
private final int x = 5;
private static final int y = 5;
}
I think x and y are the same.
What does the static qualifier matter here?
What is the advantage of the static qualifier up there for software engineering observation?
x is an instance variable while y is global.
What does that mean?
Let's look at this example:
public class A {
public A() {
System.out.println("create A");
}
}
public class B {
public B() {
System.out.println("create B");
}
}
public class C {
private static B b = new B();
private A a = new A();
}
Then a main:
public static void main(String[] args) {
C c1 = new C();
C c2 = new C();
}
Which prints:
> create B
> create A
> create A
c1 and c2 shares the same instance of B while they both create their own instance of A!
So c1.b == c2.b while c1.a != c2.a.
So summary:
there is only one and the same place/address for field b for every instance of class C (c1, c2)
but for field a there are different places/addresses in the different instances.
The example is a bit oversized with class A and B:
Even for simple fields (int, float, ...) is one and the same place/occurrence for a static field in every instance of a class.
Since it is final, it will always hold the same value.
If you don't declare it static, you will create one variable for each instance of your class. Being static means you declare the variable only once, avoiding unnecessary memory usage.
Declaring a variable as static is more memory effecient. In your example for instance, no matter how many times you create a new A(), because fields x and fields y have been declared static, they will only be allocated memory once. If you do not declare them as static, they will be allocated memory with every new class instance.
It is sensible to declare a final variable that has been initialized like yours as static because it is not able to change, and thus allocating it memory just one time is acceptable.
Essentially, it's to save memory. If the constant is always the same no matter what, then you might as well make it static so that it doesn't get created for each object. You don't want to make it static, however, if the constant is not necessarily the same for each object (for example, if your constant is initialized somewhere in a constructor).
It saves memory as it only allocates for 1 copy of the variable. If you were to make a new instance for a non-static variable for it will make a new copy for that specified instance.
Since they are final they cannot be changed so it would make sense to make them static, so when you make new instances, nothing new is allocated for the variables since they can't even be altered.
I was just trying some sample code for checking class variable overriding behavior in Java. Below is the code:
class A{
int i=0;
void sayHi(){
System.out.println("Hi From A");
}
}
class B extends A{
int i=2;
void sayHi(){
System.out.println("Hi From B");
}
}
public class HelloWorld {
public static void main(String[] args) {
A a= new B();
System.out.println("i->"+a.i); // this prints 0, which is from A
System.out.println("i->"+((B)a).i); // this prints 2, which is from B
a.sayHi(); // method from B gets called since object is of type B
}
}
I am not able to understand whats happening at these two lines below
System.out.println("i->"+a.i); // this prints 0, which is from A
System.out.println("i->"+((B)a).i); // this prints 2, which is from B
Why does a.i print 0 even if the object is of type B? And why does it print 2 after casting it to B?
i is not a method - it's a data member. Data members don't override, they hide. So even though your instance is a B, it has two data members - i from A and i from B. When you reference it through an A reference you will get the former and when you use a B reference (e.g., by explicitly casting it), you'll get the latter.
Instance methods, on the other hand, behave differently. Regardless of the the type of the reference, since the instance is a B instance, you'll get the polymorphic behavior and get the string "Hi From B" printed.
Even though A is initialized as new B(), the variable is an A. if you say
B a = new B();
you won't have that problem.
consider the code below :
class B
{
int j =100;
}
class A extends B
{
int i=10;
}
public class Test
{
public static void main(String[] args)
{
A obj =new A();
System.out.println(obj);
B obj1 =obj;
System.out.println(obj1); // here i am confused
if( obj1 instanceof A )
{
System.out.println("yes"); //here i am confused
}
}
}
here the output is :
A#35186a
A#35186a
yes
Now obj1 is an instance of class B which is superclass , so why does the toString() show it to be object of A ? Also how can instanceof operator show it to be instance of class A ?
You have to distinguish between the reference and the actual object.
B obj1 = obj;
Here you create a new reference of type B named obj1. The object referenced is still an A object though, this can never be changed.
obj1 is pointing at obj which is an instance of A (see the new A()) you have got there. On the left hand side you are just referencing the super class. Your obj1 will only be able to see methods in B. obj will be able to see all methods in B and A (subject to correct access)
From the java trail
Declaration: The code left of the = associates a variable name with an object type.
Instantiation: The new keyword is a Java operator that creates the object.
Initialization: The new operator is followed by a call to a constructor, which initializes the new object.
There isn't any toString method in your code, you print the memory place holders (Java don't allow you to see the exact location of the object in the memory).
When you do "extends" you say "A is a son of B",then in the lines:
A obj =new A();
System.out.println(obj);
You create an A object and print is memory place holder (remember, A is son of B, so if you want to describe it, imagine a box called A and a box called B connected to her (on top of her, because it's her father)).
Now in the next lines:
B obj1 =obj;
System.out.println(obj1); // here i am confused
You create another object called obj1 and you assign him the memory place holder of A so, it's the first object that you created, called obj. how can you assign A object to a B? Polymorphism!1 and again you print it's memory place holder.
Next you do if:
if( obj1 instanceof A ){
System.out.println("yes"); //here i am confused
}
So, obj1 is an instanceof of A (it's a box of A and on top of her is a box of B (it's father, polymorphism)), and you print "Yes".
In polymorphism you print the lowest method, so you print the A methods if there is any, and if there isn't you "climbing up" to the father and check there and so on..
Polymorphism (computer science)
Now obj1 is an instance of class B which is superclass
That is not true, obj1 is still an instance of A. You just happen to assign a pointer of the super class to an already existing pointer of class A.
If you want an instance of class B just do this:
B b = new B();
If you want an instance of class A you can do this:
A a1 = new A();
or
B a2 = new A();
The later, a2, is correct because A is of type B. However, a2 is still an instance of A, because we used new A().
The question might be a very basic one. I am new to Java so please bear with me.
My code:
class A
{
int b=10;
A()
{
this.b=7;
}
int f()
{
return b;
}
}
class B extends A{ int b; }
class Test
{
public static void main(String[] args)
{
A a=new B();
System.out.println(a.f());
}
}
Why is the output 7? Doesn't class B get its own instance variable b?
It would but the function f can only see the version of b that is in A. Thus the function returns 7.
If you were to copy the function f into the class B you would see the member b of the class B being returned.
As Hiding instance variables of a class explains, Java variables are not polymorphic. The 2 b variables are 2 different variables as you would expect, but when you call the function A.f it can only see the one b variable that A has. So it returns A.b and NOT B.b.
So to answer your question, class B DOES get its own instance variable b, and it is completely independant of A.b but you currently have no way to access it so you cannot see its value.
Your type reference is A:
A a = new B();
Thus instance fields/static fields and static methods will be provided from A, as long as concerned method (in your case f()) isn't overriden by B.
In other languages, as Scala, variables can be redefined in subclasses and targeted even from a supertype reference.
So, I have this:
public class A {
public int a = 0;
public void m(){
System.out.println("A"+a);
}
}
And this:
public class B extends A {
public int a = 5 ;
public void m (){
System.out.println("B"+a);
}
public static void main(String[] args) {
A oa = new A();
B ob = new B();
A oab = ob;
oa.m();
ob.m();
oab.m();
System.out.println("AA"+oa.a);
System.out.println("BB"+ob.a);
System.out.println("AB"+oab.a);
}
}
Output:
A0
B5
B5
AA0
BB5
AB0
I don't understand why oab.m(); output is B5 instead of A0. Can someone explain this to me?
That's the whole point of polymorphism. The concrete type of oab is B (since the object was created with new B()). So the method B.m() is called.
Look at the Animal example in http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29 to understand why it's useful. When you have an animal, and this animal is a Cat, you expect it to say "Meow!" when you make it talk.
B ob = new B();
A oab = ob;
Similar as
A oab=new B();
I don't understand why oab.m(); output is B5 instead of A0
Because you creating object of B and referencing it to A so m() is being inherited and that's why B's version of m()is being called.
A oa = new A();
B ob = new B();
A oab = ob;
From the code above ob is an instance of class B. It can be stored in a variable of class A as A extends B. But as the stored Object instance is of B and hence it is not aware of A's m() function.
Hence the out put is B5
In inheritance actual method invocation depends on the type of the actual object and not on the type of the reference.
B ob = new B();
A oab = ob;
Here oab is a reference variable of type A but it is pointing to object of type B i.e. ob so at runtime oab.m() will invoke overridden m() method from class B
In Java there is something like late binding (polymorphism). It means that code of method is not linked while compilation time (early binding), but while runtime. While invoking oab.m(); JVM is checking actual type (class) of object from aob reference (in your case B) and based on that info invoking code of method from that class. That is why oab.m(); returns B5.
You also need to know that late binding works only for methods, not fields. For fields value will be determined by reference type, so oab.a will return 0 not 5.
Imagine you had the following:
public class C extends A {
public int a = 7 ;
public void m (){
System.out.println("C"+a);
}
Now if you had this in your Main method...
C oc = new C();
A oac = oc;
oac.m();
...you would want that last call to output the stuff that is specific for the class C.
The point is that B is an A, and C is an A, but each of them have more specific versions of the values that an A contains, and when you ask for those data, the specific versions of them should be returned.
Now you can do this:
// Get an instance of B or C, but you don't
// care which - could be either:
A someVersionOfA = getAnInstanceOfA();
// This works no matter if you've got an instance
// of B or C, but the result should vary accordingly:
someVersionOfA.m();
As someone else mentioned, think of A as "Animal", B as "cat", and C as "Dog". If m() means "Make some noise", then calling m() should result in "Meow" or "Woof!" depending on on the instance getAnInstanceOfA() returned.
You have just copied the internal address of B to A one, and replacing it.
B inherit from A, so no compilation problem.
Finally, the reference to A is destroyed, it is now a copy of reference to B