Let say I have the following java classes:
Class A:
public class A {
private int x;
public A(int x){
this.x = x;
}
public static void main(String[] args) {
A a = new A(1);
B b = new B(1,2);
System.out.println((A)b.x);
}
}
Class B:
public class B extends A {
public int y;
public B(int x, int y){
super(x);
this.y = y;
}
}
Why does the compiler marks the access to x on this line
System.out.println((A)b.x);
as an error, even though I'm trying to access x from the class in which it is defined?
Is it because of:
1. the use of polymorphism?
2. the use of a static method?
3. the use of the main method?
You need to make it ((A)b).x to properly type cast it
Note : You are trying to type cast the property x to type A. That's the error!
int x is private therefore it can't be reached from outside of the scope of the class. You could mark it as protected. This way it will still have limited scope. Classes that extend A will be able to access the variable freely.
This is because the dot operator has precedence over the cast operator. This will work, because it forces the cast operator to be applied before the dot operator:
System.out.println(((A)b).x);
Demo on ideone.
When you write (A)b.x, the compiler try to cast b.x into A, but x is an int
Moreover, you don't need to cast b into A and you can't access b.x because x is a private field.
You may need a getter for this, like b.getX()
You have follwing issues
Compiler will show "Field not visible" Error,Because you trying to access private method of parent class
Syntactically. operator has precedence over cast operator
And another impotent thing is that No need to cast a child object to parent to access parent specific members, Because they are already inherited to the child, Here the member you are accessing is private ,which is not inherited. Even if you cast to parent you cant access private members using child object.
Because you are trying to cast an int into A. You need to wrap the cast around the object and then call .x.
Your call is equivalent to (A)(b.x), when it should be ((A)b).x.
public static void main(String[] args) {
A a = new A(1);
B b = new B(1,2);
System.out.println(((A)b).x);
}
Basically, two issues exist here.
One being that int x is private so it cannot be accessed from the sub-class.
Now even if you change the access criteria of int x to publicor protected; the code will still not work because (A)b.x will try to typecast an integer (read x) to an object (read A). Instead of this, you should use ((A)b).x
Related
In a normal class,
public class MyClass {
int a =12;
}
works fine.
But,
public class MyClass {
int a =12;
int b;
b=13;
}
this gives a compilation error.
I know I am trying to access a field without using an object of that class, so I even tried this->
public class MyClass {
int a =12;
int b;
MyClass m= new MyClass();
m.b=13;
}
but even this doesn't seem to work.
I can accept the fact that this is how things work and move on. But does anyone know the logic behind this?
Thank you in advance.
int a = 12;
This is a variable declaration with initialisation.
b=13;
This is an assignment; a statement; it cannot be part of the declaration. It has to be part of the constructor or method.
It is how Java object definition works.
variable/field declarations
constructors
methods (static or non-static)
You can do it in one of the following two ways:
Use the initialization block as follows:
int b;
{
b = 13;
}
Do the following in the constructor:
b = 13;
Check https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html to learn more about it.
This is a simple example of inheritance where there is a shadowed variable x.
class A{
int x=1;
}
class B extends A{
int x=2;
}
class C extends B{
int x=3;
int y;
}
How can I reference the shadowed variable x of class A in class C?(I want something like y=super.super.x; that works well.)
Not as hard as you might think. (While I strongly encourage avoiding this situation,) if you have a class C that inherits from class B, which in turn inherits from class A, all of which implement a public field x, then using super is usually the wrong way to go about it.
Instead, given class C, try this:
((A)this).x; //don't forget the parentheses!
that will give you the value of x for A. Also,
super.x == ((B)this).x;
which is generally why, for single steps, we usually just use super.
Hopefully that helps.
To my knowledge, there is no way to achieve this the way you imagine. Your best bet would be to implement an access method in your class B:
class B extends A{
int x=2;
protected int getXFromA() {
return super.x;
}
}
This way you would be able to access the value of x as defined in class A from class C.
I would be very interested in your use case, though. Considering object oriented design, what reason could there be to directly access A's members from C? If this is the case, from an OOP perspective, C could not really be considered a proper subclass of B anymore.
class A {
int x = 1;
}
class B extends A {
int x = 2;
}
class C extends B {
int x = 3;
int y = ((A) this).x;
}
Note that shadowing is generally discouraged due to the confusion it can cause.
class A {
int super_var = 1;
}
class B extends A {
int sub_var = 2;
}
public class Demo{
public static void main(String []args){
A a = new B();
System.out.print(a.sub_var); //compile error
}
}
why this will end with a compile error ? reference (a) referencing to an Object of B it has sub_var so why is it restricted ? why reference (a) can access only the fields in A ?
Let's say you have these classes:
public class Animal() {
// ...
}
public class Fish extends Animal() {
public void swim() {...}
}
If you declared an Animal:
Animal x = new Fish();
and you called the swim() method
x.swim();
Would you expect it to work? I don't think so, because not every animal can swim. That's why you have to explicitly specify that the animal x is a Fish:
((Fish) x).swim();
In your case, if you wanted to call that method, you should specify (technically, it's called cast) the type:
System.out.print(((B)a).sub_var);
Note:
This works similar for methods and variables. I used a method in the example since it's more illustrative.
Edit:
Let's see this example:
Animal x;
if (some_condition)
x = new Fish();
else
x = new Cat();
x.swim();
This restriction exists, because Java won't know if, at execution time, the object assigned to x will have the method swim(). So to avoid this, you have to cast to the respective type to call a method that doesn't exist in superclass.
At first it does sound like it should work. (And in some languages it probably does.) But think about this example:
public class Demo {
public static void main(String []args){
A a = new B();
print( a );
}
public static void print( A arg ) {
System.out.print(arg.sub_var); //compile error
}
}
This functionally does the same thing but the print is in another method. If your version worked, this one could be expected to work too.
But what if someone then does this?
Demo.print( new A() );
This should fail because A doesn't have a sub_var. It would have to throw some kind of runtime error instead.
So the design decision in Java was not to allow this and if you declare a local variable/field/method parameter as type A, then you can only access things that every object that is either A or a subclass is guaranteed to have.
If you want to access more, you need to cast it to the subclass, which will throw an exception if you try it on an object that doesn't fit.
A a = new A();
System.out.print(((B)a).sub_var); //ClassCastException is thrown here
You can not access B members with the reference of Parent object A.
Instead change your println statement like below to access,
System.out.print(((B)a).sub_var);
Is there a variable called sub_var in the parent class ? No. That is why you get the error -
sub_var cannot be resolved or is not a field
See this
System.out.print(a.super_var); //okay
System.out.print(a.sub_var); //compile error
you create an object of type B and assign it to a variable of type A. The type A does not declare sub_var. This field is declared only in type B. the compiler only sees what is declared in type A, although the variable is instantiated to an object of type B.
If you want to access sub_var you would have to cast a to B.
System.out.println( ((B)a).sub_var);
The sub_var is in class B, so you can only access through a reference of class B. To the compiler A a = new B(); means a is an instance of class A.
I don't understand how exactly it works.
We have two class A and B. Class B extends A.
Class A have x attribute, and test method which modify this attribute.
Class B have x attribute, and test method which modify this attribute.
public class A {
int x;
public void test() {
this.x = 1;
System.out.println("A" + getX());
}
int getX() {return x;}
}
public class B extends A {
int x;
public void test() {
this.x = 2;
System.out.println("B" + getX());
}
int getX() {return x;}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();
System.out.println(a.getX());
System.out.println("point 1");
a = new B();
a.test();
System.out.println(a.x);
}
}
Output:
A1
1
point 1
B2
0
My prediction about last line of output was 2, but is 0. Why is 0?
Let's understand these lines of code:
a = new B();
a.test();
System.out.println(a.x);
You create a new object of B. It will re-initialize the variable - A.x = 0 and B.x = 0.
Then you invoke a.test(), which will call the overridden method test() in class B, which will set B.x to 2 using this.x = 2;. Note at this point, A.x is still 0.
Then you access a.x, which will access the field x in class A. The fields are not polymorphic. You don't override fields, but you hide them. The variable x in B hides the variable x in A.
If both A and B have a member named x, the one in B will block access to the one inherited from A. Remove the int x; declaration from B, or explicitly use super.x, if you want to reference the one in the parent class.
Starting from begin.
When you write
A a;
You say to JVM please reserve me in memory an address for something that fits A.
after when you do
a = new A();
You say to JVM, create a new object of class A and save the address to it under a
when you do this;
a.test();
You say to JVM, go to memory address a and from object there invoke method test().
Next thing what you do is this:
a = new B();
You say to JVM, create a new object of class B and save the address to it under a. No error here as B fits A as is a child class.
(You loose the connection with object of class A ass you changed it to B).
next operation is
a.test();
you also know this, but this time under address a is instance of class B. This time JVM search for the method in class B, if not fond then will search in class A.
I think you should start over with the Inheritance/Polymorphism concepts first.
But to make it clear: You have an object "a" which is declared as with type "A". Now, when you call the method test (which is overriden inside B in this case), the JVM calls the actual objects method. So, before "point 1" a.test calls A's test method, after "point1" it calls B's test method.
The problem is that this feature (called polymorphism) works only on methods. Whilst when you call an instance variable (as a.x) , the JVM calls the declared object variable. In this case is A. If you make a cast first, you'll get the right value: ((B)a).x
Note, the difference between actual and declared object is based on the type after the "new" operator (like new B()) and that in the object declaration
class Myclass{
int x;
Myclass (int i){
x = i;
}
}
That is the code I have in my book. I wanted to know if this code would work?
class Myclass{
int x;
Myclass (x)
}
I also could try
class Myclass{
int x;
Myclass (int x)
}
in response to my first answer...would this work?
The latter code would not work because in Java you have to explicitly state the type. (There are no implicit type declarations)
You may have a parameter or local variable with the same name as an instance variable, yes. In that case, the parameter or local variable will shadow the instance variable. To refer to the instance variable in such a case, use:
this.x
For example, it's common to see this pattern:
class MyClass {
private int x;
public MyClass(int x) {
this.x = x;
}
}
Note that, as Josh M points out, it is not possible to omit the type. If that is what your question was about, then no, you may not.
This will compile:
class Myclass {
int x;
Myclass (int x) {
}
}
However, when you do this you end up with two variables with the same name, the instance variable x, which can be referred to explicitly inside the constructor (or any other class method) as this.x, and the local parameter variable x local to the constructor. If you just refer to x in the constructor you'll get the local one. This is referred to as variable shadowing.
Even though you've decided to give these two variables the same names in your source code, in the code the compiler produces they are completely unrelated. You might as well have named the parameter y.
An experiment to try that might help understanding this is to give the variables different types. Make your instance variable a boolean, for instance. Then you can try different things and see that they really are completely different variables that just happen to have the same name.
After #Chris Hayes' and #Samuel Edwin Ward's answers, here's one trick.
class MyClass {
private int x;
public MyClass(final int x) {
this.x = x;
}
}
The final modifier tells the compiler that that x cannot be modified. If you accidentally write
class MyClass {
private int x;
public MyClass(final int x) {
x = x; // Oopsie!
}
}
the compiler will complain.