Why this protected member is not visible in the subclass [duplicate] - java

This question already has answers here:
Understanding Java's protected modifier
(6 answers)
Closed 7 years ago.
I have a problem understanding protected members inheritance and visibility.
I know it is visible in the same package and subclasses.
But in the following code it is not visible in a subclass.
A.java
package a;
public class A {
public static void main(String[] args) {
}
protected void run() {
}
}
B.java
package b;
import a.A;
public class B extends A {
public static void main(String[] args) {
B b = new B();
b.run(); // this works fine
}
}
C.java
package b;
import a.A;
public class C extends A{ // it will not work also if extends B
public static void main(String[] args) {
B b = new B();
b.run(); // this is the problem; not visible
}
}
Why b.run() in the last class is invisible?

This is because class C can see A's protected methods from within its own inheritance tree. But it's not allowed to access A's protected methods for another class (B) from a different inheritance tree. C is not part of B's inheritance tree (by this, I mean that's it's not a parent of B), therefore the behavior is normal.
EDIT: Added documentation reference as requested
6.6.2.1. Access to a protected Member:
If the access is by a field access expression E.Id, or a method invocation expression E.Id(...), or a method reference expression E :: Id, where E is a Primary expression (§15.8), then the access is permitted if and only if the type of E is S or a subclass of S.
Applying the above to this case, because the variable b is not an instance of C or a subclass of C, access to the protected method b.run() is not allowed.
Also addressing Codebender's comment about the packages. Note that, if the C class would have been defined in the same package as the A class, where the protected run() method is defined, then the above rule wouldn't apply, and you would be able to access the method as shown in your code.

Related

Why I'm facing with 'clone() has protected access in java.lang.Object' compiler error? [duplicate]

This question already has answers here:
Why java.lang.Object can not be cloned?
(10 answers)
Closed 4 months ago.
Object's clone method is protected, therefore it can be accessed in sub classes (class A), so why am I getting 'clone() has protected access in java.lang.Object' compiler error? I thought, that all Java classes are sub classes of Object. Thanks in advance.
The code below raises the compiler error:
public class A {
public static void main(String[] args) {
Object o = new Object();
o.clone();//error
}
}
But this one compiles perfectly, don't they have the same semantics tho?
public class A {
protected void foo() {
}
}
public class B extends A {
public static void main(String[] args) {
A a = new A();
a.foo();
}
}
No, they don't.
protected means 2 things:
It's like package, _and that explains why your second snippet can call foo(). It's not about the fact that B extends A, it's that A is in the same package as B.
Subclasses can invoke it.. on themselves only. Trivially (but this doesn't work if its final), you can simply override it, implement it as return super.clone(); and now you can call it just fine.
protected members can be accessed anywhere in the same package and outside package only in its child class and using the child class reference variable only, not on the reference variable of the parent class. We cant access protected members using the parent class reference.

access protected member in java by calling it from an object [duplicate]

I have a class called A in package1 and another class called C in package2. Class C extends class A.
A has an instance variable which is declared like this:
protected int protectedInt = 1;
Here is the code for class A
package package1;
public class A {
public int publicInt = 1;
private int privateInt = 1;
int defaultInt = 1;
protected int protectedInt = 1;
}
And here is the code for class C:
package package2;
import package1.A;
public class C extends A{
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
}
Eclipse underlines the last line in C.go() and says "A.protectedInt" is not visible. It seems that this conflicts with the definition of the "protected" keyword, given the Oracle documentation says:
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
What's going on here?
What's going on here?
You've misunderstood the meaning of protected. You can access the protected members declared in A from within C, but only for instances of C or subclasses of C. See section 6.6.2 of the JLS for details of protected access. In particular:
Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.
In addition, if Id denotes an instance field or instance method, then:
[...]
If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.
(Emphasis mine.)
So this code would be fine:
C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);
Since C is inheriting A, C can directly use the protected variable of A like below
public class C extends A{
public void go(){
System.out.println(protectedInt);
}
}
As per your code, you are creating an instance of A and accessing protected variable through that instance, which violates java's rule - A protected variable is not visible outside the package
Protected means:
a) This member will be accessible to all classes in the same package through A object’s reference.
b) For different packages, this will be accessible only inside subclasses of A, say B, and the reference used can be a B instance or of any subclass of B.
Let's take an example:
Let A be a parent class in some package, say com.ex1.
Let B and C be classes in different packages w.r.t to A, say com.ex2. Also, B extends A and C extends B.
We will see how we can use protected fields of A inside B (a subclass of A).
A's code:
public class A {
protected int a = 10;
}
B's code:
public class B extends A {
public void printUsingInheritance() {
// Using this
System.out.println(this.a);
}
public void printUsingInstantiation() {
// Using instance of B
B b = new B();
System.out.println(b.a);
// Using instance of C as C is a subclass of B
C c = new C();
System.out.println(c.a);
A a = new A();
System.out.println(a.a); // Compilation error as A is not a subclass of B
}
}
C's code:
public class C extends B {
}
For protected static:
Same rules apply except that in b) now it is accessible in any subclass of A by A's class reference. Reference
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
When you are doing A a = new A(); and a.protectedInt you trying to access protected member of A which is illegal according to java standards
Instead you can do this.protectedInt directly.
No need to instantiate Protection class inside Protection2 Class. You can directly call the protected variable without instantiating the Protection class. Because Protection2 class extends Protection class. So variable automatically inherited by subclass.
Try with below code:
public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}
Within the same package where the protected member is declared, access is permitted:
package package1;
public class C extends A{
public void go(){
A a = new A();
System.out.println(a.protectedInt); // got printed
C c = new C();
System.out.println(c.protectedInt); // got printed as well
}
}
Outside the package where the protected member is declared, access is permitted if and only if by code that is responsible for the implementation of that object. In this case, C is responsible for the implementation of that object, so it could access the protected.
package package2;
public class C extends A{
public void go(){
A a = new A();
System.out.println(a.protectedInt); // compiler complains
C c = new C();
System.out.println(c.protectedInt); // got printed
}
}

Accessing protected members [duplicate]

This question already has answers here:
Protected member access from different packages in java - a curiosity [duplicate]
(9 answers)
Closed 7 years ago.
I am very confused with this . can any one clear me why it was not allowing the code that i have placed n comments
package pack1;
public class A {
protected void m1() {
System.out.println("This is very imp point");
}
package pack2;
import pack1.A;
class B extends A {
public static void main(String arg[]) {
// A a1 = new A();
//a1.m1();
B b1 = new B();
b1.m1();
//A a2 = new B();
//a2.m1(); }
}
}
Method m1 is protected, so it's accessible across packages to child classes.
Therefore, instances of B will be able to invoke or #Override m1.
Not so main static methods, even if pertaining to class B: the scope is different.
You can either make m1 public in A, or invoke it within your instance of B (e.g. in the constructor, etc.).
You can also override A's m1 in B and give it less access restrictions, thus making it public in this instance: then you could access it on an instance of B from your main method as you're trying to do.
You can access the protected members declared in A within B, but only for instances of B or subclasses of B. Check out this answer

Understanding scope of private method [duplicate]

This question already has answers here:
Private methods in Inheritance
(9 answers)
Closed 7 years ago.
A friend of mine asked this question to me. Why the following code does not give error on invoking aa.x()?
I understand that aa is a reference to object of class B but is invoking private method of class A inside the method of class A where it is visible and hence accessible.
Is my understanding correct? Or is there any other reason behind this?
public class A {
public void xyz() {
System.out.println("A");
}
private void x() {
System.out.println("A:x");
}
public static void main(String[] args) {
B b = new B();
A aa = b;
aa.x();
aa.xyz();
B bb = (B) aa;
bb.xyz();
bb.xyz12();
}
}
class B extends A {
public void xyz() {
System.out.println("B");
}
public void xyz12() {
System.out.println("B-12");
}
}
I can't immediately find a duplicate using a subclass, but fundamentally it's the same answer as the answer to this question.
There are two things that govern access to x:
Where the code is that's doing the access. Since x is private to A, the code accessing it must be part of a method in A. It can't be in a subclass (B) or an unrelated class.
What kind of reference you're using. If you have an A reference, you can access x on it. If you have a B reference, you can't, even though your code is part of an A method. You could cast it to A and then access x, but you can't do it directly with a reference of type B.
It is only visible because the main method where it is invoked is contained in class A. Move it to class B and it will not work
As the private methods are not inherited, a superclass reference calls its own private method.
Your main method is the method of A, therefore it can can call x() private method.
private modifier—the field is accessible only within its own class.

Descendant not seeing clone() due to access privilige violation? [duplicate]

I have a class called A in package1 and another class called C in package2. Class C extends class A.
A has an instance variable which is declared like this:
protected int protectedInt = 1;
Here is the code for class A
package package1;
public class A {
public int publicInt = 1;
private int privateInt = 1;
int defaultInt = 1;
protected int protectedInt = 1;
}
And here is the code for class C:
package package2;
import package1.A;
public class C extends A{
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
}
Eclipse underlines the last line in C.go() and says "A.protectedInt" is not visible. It seems that this conflicts with the definition of the "protected" keyword, given the Oracle documentation says:
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
What's going on here?
What's going on here?
You've misunderstood the meaning of protected. You can access the protected members declared in A from within C, but only for instances of C or subclasses of C. See section 6.6.2 of the JLS for details of protected access. In particular:
Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.
In addition, if Id denotes an instance field or instance method, then:
[...]
If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.
(Emphasis mine.)
So this code would be fine:
C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);
Since C is inheriting A, C can directly use the protected variable of A like below
public class C extends A{
public void go(){
System.out.println(protectedInt);
}
}
As per your code, you are creating an instance of A and accessing protected variable through that instance, which violates java's rule - A protected variable is not visible outside the package
Protected means:
a) This member will be accessible to all classes in the same package through A object’s reference.
b) For different packages, this will be accessible only inside subclasses of A, say B, and the reference used can be a B instance or of any subclass of B.
Let's take an example:
Let A be a parent class in some package, say com.ex1.
Let B and C be classes in different packages w.r.t to A, say com.ex2. Also, B extends A and C extends B.
We will see how we can use protected fields of A inside B (a subclass of A).
A's code:
public class A {
protected int a = 10;
}
B's code:
public class B extends A {
public void printUsingInheritance() {
// Using this
System.out.println(this.a);
}
public void printUsingInstantiation() {
// Using instance of B
B b = new B();
System.out.println(b.a);
// Using instance of C as C is a subclass of B
C c = new C();
System.out.println(c.a);
A a = new A();
System.out.println(a.a); // Compilation error as A is not a subclass of B
}
}
C's code:
public class C extends B {
}
For protected static:
Same rules apply except that in b) now it is accessible in any subclass of A by A's class reference. Reference
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
When you are doing A a = new A(); and a.protectedInt you trying to access protected member of A which is illegal according to java standards
Instead you can do this.protectedInt directly.
No need to instantiate Protection class inside Protection2 Class. You can directly call the protected variable without instantiating the Protection class. Because Protection2 class extends Protection class. So variable automatically inherited by subclass.
Try with below code:
public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}
Within the same package where the protected member is declared, access is permitted:
package package1;
public class C extends A{
public void go(){
A a = new A();
System.out.println(a.protectedInt); // got printed
C c = new C();
System.out.println(c.protectedInt); // got printed as well
}
}
Outside the package where the protected member is declared, access is permitted if and only if by code that is responsible for the implementation of that object. In this case, C is responsible for the implementation of that object, so it could access the protected.
package package2;
public class C extends A{
public void go(){
A a = new A();
System.out.println(a.protectedInt); // compiler complains
C c = new C();
System.out.println(c.protectedInt); // got printed
}
}

Categories

Resources