Some trouble with inner class visibility - java

I'm facing java inner class and I'm having some trouble with outer variables visibility.
class A {
private int x = 5;
class B extends A{
public void fun(B b){
b.x = 10; //here
}
}
}
Why I can't do something like this (see the "here" tag) if there are no visibility restrictions between inner and outer class? I'm really not understanding these rules.

In your example the member variable x is not a property of class B so b.x = 10 makes no sesne, hence the error, it's nothing to do with visibility rules. Trying x = 10 works fine, which is a short-cut for A.this.x = 10 or super.x = 10.

Modifier private cannot be accessed in sub classes.
class A {
private int x = 5; // The issue is in `private` in this line
class B extends A{
public void fun(B b){
b.x = 10; //here
}
}
}
If you remove the modifier private and change it to default, public OR protected, you will be able to access the variable.
Please go through the link for better understanding.
UPDATE:
Remove extends keyword (Now Class B will not be a sub class but only an inner class), and the variable x will only be accessed using this OR super keyword. The usage is elaborated at link

you need know this three private,protected,default,publicaccess specifiers
private variables only can be modified in the itself class.not include subclass
default variables can be modified in same package.
protected variables can be modified in subclass and in same package and itself
public variables can be modified any where.
you can saw this on this link
beside.if you use this example ,this can modified your variables with usingsuperspecifiers to access your visiable
class A {
private int x = 5;
class B extends A{
public void fun(B b){
b.x = 10; //here error
super.x=1;//this is ok
}
}
}
this b.x = 10; //here error this problem is b is a parm of a methods not a member-variable or a super class variable.

This one is quite special. Inner class can access the private field of the outerclass. This can be shown with the fun(A) method
class A {
private int x = 5;
class B extends A{
public void fun(A a){
a.x = 5; //Valid since we are in the same class (inner-class can access private field)
}
}
Now, if you have a B parameter, this is a bit different because it will try to use the inheritence instead of the outer-inner link :
public void fun(B b){
b.x = 10; //Access using inheritence, not OK for private field
((A)b).x = 10; //Casting into A to be able to access the private field (just like fun(A).
}
Note that this is a problem because you update a reference receive in parameter, you can update the current inner instance easily
public void fun(){
x = 10; //OK : access to A.x from inner class
super.x = 10; //OK : same
this.x = 10; // KO : trying to access a private variable from B scope
}

Related

Inner class object

I couldn't understand the behavior of the below code.
My expectation was that it should print 100 in both println() methods. Why the result is different?
If I uncomment getX() method in inner class, then the output of println() methods are the same which is 100.
I couldn't figure out the reasoning of different behavior. Please help me to understand.
public class Foo {
public static void main(String[] args) {
MyOuter outerObj = new MyOuter();
MyOuter.MyInner innerObj = outerObj.new MyInner();
innerObj.setX();
System.out.println("x: " + innerObj.getX()); //x: 3
System.out.println("x: " + outerObj.getX()); //x: 100
}
}
class MyOuter {
private int x = 3;
public int getX() { return x; }
class MyInner extends MyOuter {
public void setX(){ x = 100; }
// public int getX() { return x; }
}
}
From MyInner's perspective, there are two private int x fields in play here:
One field super.x that is inherited from MyOuter, but inaccessible because it is declared as private, and MyInner as an inheriting object cannot access this field.
One field MyOuter.this.x from the sorrounding MyOuter-instance (since MyInner is a (non-static) inner class, it is always bound to an instance of the surrounding MyOuter), that is accessible.
The method setX() in MyInner cannot access the inherited field super.x, thus it accesses the field MyOuter.this.x and sets its values to 100. A consecutive call on the surrounding MyOuter's getX() will return 100.
The call innerObj.getX() (which is inherited from MyOuter and can access super.x) returns the value of the inherited field super.x (still having its initial value of 3).
If we remove the extends MyOuter from and include the getX()-method in MyInner, the code behaves as expected.
The fact that MyInner cannot access the inherited field private x is confusing at first, but the behaviour is actually in line with the behaviour of the keyword protected in the context of static mehthods in inheriting classes as discussed in this post by Hariharan

re-inheritance static field from class and interface

interface A {
public static String name = "A";
}
interface B {
public static String name = "B";
}
class X implements A { }
class Y extends X implements B { }
public void test_getField() {
try {
assertEquals(B.class.getField("name"), Y.class.getField("name"));
} catch (NoSuchFieldException e) {
fail("Got exception");
}
}
Why does Y.class.getField("name") return B.name instead of A.name?
Is there any answer in the Java specification?
The direct superinterface will be searched before superclass, see the doc of getField:
The field to be reflected is determined by the algorithm that follows.
Let C be the class represented by this object:
If C declares a public field with the name specified, that is the
field to be reflected.
If no field was found in step 1 above, this
algorithm is applied recursively to each direct superinterface of C.
The direct superinterfaces are searched in the order they were
declared.
If no field was found in steps 1 and 2 above, and C has a
superclass S, then this algorithm is invoked recursively upon S. If C
has no superclass, then a NoSuchFieldException is thrown.
The key point here is that you're using reflection and getting unexpected behavior.
Although you already have the reflection algorithm, I will add a visual example.
First of all, using normal access you will get:
class Y extends X implements B {
public void test() {
System.out.println(name);
}
}
Error:(29, 36) java: reference to name is ambiguous both variable
name in com.test.A and variable name in com.test.B match
Now considering an example:
class Y extends X implements A, B {}
public class Main {
public static void main(String[] args) throws NoSuchFieldException {
Y y = new Y();
System.out.println("Y : " + y.getClass().getField("name"));
}
}
The output will be:
Y : public static final java.lang.String A.name
Changing signature to
class Y extends X implements A, B {}
Gives us output:
Y : public static final java.lang.String B.name
The direct superinterfaces are searched in the order they were
declared.
Further observation shows that actually we can get both names like:
class Y extends X implements A, B { }
public class Main {
public static void main(String[] args) throws IllegalAccessException {
Y y = new Y();
Field[] fields = Y.class.getFields();
for (Field field : fields) {
System.out.println(field.get(y));
}
}
}
Output:
A
B
And for both class Y extends X implements B { } and class Y extends X implements B, A { }:
B
A
The first name resolved in runtime comes from first implemented interface (direct superinterface) because it has higher precedence, then comes the value from the second interface, then the value from the superclass.
When you calling Y.class.getField("name") you're getting the first resolved name which comes from first direct superinterface - A.
This is an interesting question. Let's first simplify this a bit
static class Parent {
public int x = 1;
}
static class Child extends Parent {
public int x = 2;
}
public static void main(String[] args) {
Child c = new Child();
Parent p = c;
System.out.println(c.x);
System.out.println(p.x);
}
What do you think this will print?
It will be 2 1Instance variables are inherited, but they are not overridable. This is called hiding, Parent’s x is hidden by Child’s x. Instance variables are inherited, but they are not overridable. This is called hiding, Parent’s x is hidden by Child’s x.
The second line though… Where are we pulling x from? We do have a Parent reference, but it’s pointing to a Child instance, right? It’s like Child has two different variables with the same name; one it declares, one it inherits. Does it?
Arrays.stream(Child.class.getFields())
.map(Field::getName)
.forEachOrdered(System.out::println); // x x
It’s like Child has two fully qualified variables and depending on the reference you can access one or the other.
Now to your example (a bit simplified):
interface First {
int x = 3;
}
interface Second {
int x = 4;
}
static class Impl implements First, Second {}
What do you think this will print?
Arrays.stream(Impl.class.getFields())
.map(Field::getName)
.forEachOrdered(System.out::println);
As in the previous example, it will print x twice, the meaning of this is explained above.
Knowing this, let's go to your question (again, a bit simplified):
interface First {
int x = 1;
}
interface Second {
int x = 2;
}
class Impl implements First, Second {
}
Field left = First.class.getField("x");
// you might think that this will fail, since Impl has two variables x...
Field right = Impl.class.getField("x");
if (!left.equals(right)) {
throw new AssertionError("Aren't they equal?");
}
As the way this is written right now, this will NOT throw the AssertionError.
The idea here is that Field#equals uses 3 things for equality: type, name and declaringClass. The first two obviously match, so all we care about is the last one. And this is where the JLS comes at help which the other answer has already provided.
That is the reason btw, that if you change the order of interface declarations : class Impl implements Second, First that code will throw the AssertionError. Because now, x will be resolved from Second (in the order of the declaration... ), but we compare it with First.

What is the difference with 'protected' and 'protected-static' variables?

I read a book for OOP and
an example about 'protected' access modifier is strange for me.
Summary of example
This example is to test how 'protected' reserved word effects to variables.
ClassA has 2 protected variables (static / non-static)
package a;
public Class A {
protected int a;
protected static int b;
}
ClassB is derived from ClassA and located another package
ClassB.test has a method to check accessibility (Cannot run)
package b;
public Class B extends ClassA {
ClassA x = new ClassA();
// [O] : Executable
// [X] : Not-executable
void test() {
a = 1; // [O] : Derived from ClassA
b = 1; // [O] : Derived from ClassA
// [X] : a is protected, so only accessible within codes in derived class
x.a = 1; // A)
// [O] : I don't know why it is executable
x.b = 1; // B)
}
}
Actually, b is 'protected' so I thought it cannot be accessed by instance variable like x.a = 1;
But it can be accessible with 'static' keyword.
How can I understand for this?
Shortly A) is fine, but why is B) executable ?
The static keyword means that variable belongs to the class itself instead of the objects of said class. You could replace your call to x.b with ClassA.b. Since ClassB extends ClassA, all protected static variables are accessible for all methods of ClassB at all time.

Favoring static class usage over variable with same name

Class B extends Class A, Class A has a variable named K, I have a static Class named "K" also. Is there a way inside class B to favor using the static class K over the inherited variable K?
(I am working with decompiled code that was obfuscated, I cannot rename either of the versions of K)
You may need to refer to the class K with its full name, ie myPackage.K
Since K is in the default package, I think your only options will be to refer to class K using reflection or else write a class to wrap K so you can use a different name. Or if you're after some static members of K, you could use static imports to get at them, too.
Does this work?
class A {
int X;
}
class B extends A {
static class X {}
void foo() {
X = 5; // A.X variable
B.X x = new B.X(); // B.X nested class
}
}

basic exercise in java

I have two classes A and B as follows:
public class A {
private int salary = 0;
protected void calculate() {
salary = 400;
}
protected A() {
calculate();
}
}
public class B extends A {
private int salary = 0; // (1)
protected void calculate() {
System.out.println("calculating salary...");
salary = 700;
}
public static void main(String[] args) {
System.out.println(new B().salary); // (2)
}
}
Consider line (2): I don't understand why new B().salary is valid because the specifier of salary in line (1) is private. Could you help me explain it?
You can access B.salary because your code is executing inside the class B.
A common misconception of private (or all access modifiers, in fact) is that it acts on a per-object basis, which is not true. A private field is private to the whole class. So every instances of B can access the salary field of each other B object. Even static code in B can do that.
Also note that you're needlessly complicating matters by introducing the class A: it has no actual effect on your example, you can simply leave it out.
I don't see any private constructor of B so new B() is valid + the private field is accessible within same class
private applies to things outside the class definition, everything inside the class definition can see them.
main is a (static) member of B, so it can see private members.
Every class has access to its private parts.
It is valid since main is inside the B class, which means all fields (even private) are visible to it.
If you move main to another class, it will not be valid anymore.
Private fields can be accessed only from within the same class. So salary can only be accessed from class B.
Since your main method is in class B, you can access it.
salary in line 2 is referring to the salary you declared in class B, and your main method is part of class B so main can see any private stuff of B.
Every class has access to its private members. And "salary" is in class, along with your main method. That's why main method can access "salary".
Line 2 is the same as doing this:
B bObject = new B();
System.out.println(b.salary);
You can access the private variable because "bObject" is of type B. Now what you couldn't do is:
A aObject = new A();
aObject.bSalary;//if you changed the name of the salary variable to bSalary

Categories

Resources