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
}
}
Related
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
}
}
I have three classes: one base class A and two classes B and C that both extend A. A and B are in the same package and C is in a different package.
Both, B and C have a protected member variable. A has a method (lets call it reflect) that uses reflection and a string input to accesses a field with this name of a subclass via the this pointer.
Calling reflect from a B object is fine, but calling it from a C object results in an IllegalAccessException. I can not understand this exception, because this means that C has no access rights to access its own member variable. Why doesn't java allow this reflection?
Here is a MWE to clarify what I mean:
In parent/A.java:
package Parent;
public abstract class A {
public Object reflect(String parameter) throws NoSuchFieldException, IllegalAccessException{
Class cl = getClass();
return cl.getDeclaredField(parameter).get(this);
}
}
In parent/B.java:
package Parent;
public class B extends A{
protected Integer b;
public B(Integer b){
this.b = b;
}
}
In parent/child/C.java:
package Parent.Child;
import Parent.A;
public class C extends A{
protected Integer c;
public C(Integer c){
this.c = c;
}
}
and a small main:
import Parent.A;
import Parent.B;
import Parent.Child.C;
public class test {
public static void main(String args[]) {
B j1 = new B(10);
C j2 = new C(20);
try{
Integer b_copy = (Integer)j1.reflect("b");
System.out.println(b_copy); // prints "10"
Integer c_copy = (Integer)j2.reflect("c"); // throws java.lang.IllegalAccessException: Class Parent.A can not access a member of class Parent.Child.C with modifiers "protected"
System.out.println(c_copy);
} catch (NoSuchFieldException | IllegalAccessException e) {
System.out.println(e);
}
}
}
Thank you very much!
Reflection allows you to bypass the access protection mechanism but you must explicitly instruct it to do so:
package Parent;
public abstract class A {
public Object reflect(String parameter) throws NoSuchFieldException, IllegalAccessException{
Class cl = getClass();
java.lang.reflect.Field f = cl.getDeclaredField(parameter);
f.setAccessible(true);
return f.get(this);
}
}
In particular, you may be having the issue with C because you're actually accessing C's protected variable from A since that's where you're performing the reflective call. You'd get the same access violation if you tried accessing C's field directly from A.reflect().
The exception is quite clear:
java.lang.IllegalAccessException: Class Parent.A can not access a member of class Child.C with modifiers "protected"
The method is running under the namespace (=package) of class A.
The protected access modifier implies package-visibility.
Notice that A is not a subclass of B or C, therefore the visibility of member variables for subclasses plays no role here.
However, since B is in the same package as A, and the member b is marked as protected, it is also package-visible, and therefore can be accessed from A.
For C, this is not the case, because A is neither a subclass of C, nor is C in the same package as A.
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.
I have three classes A,B and C.
I have created object of class A in class B and I have inherit class B to class C.
Do the object of class A also inherit to class C?
Can I access member functions of class A through class C?
You have used composition between A and B (B encloses an instance of A) and inheritance between B and C. So from C you can "get at" methods in B by using the super keyword. You may (depending on scope) thus also access members of A from within C, but you are not doing it directly by inheritance, as would be the case if C inherits from B and B inherits from A.
Here is a small example for your case use it,
class A
{
String varOfA="Class A";
private String locOfA="Local variable";
}
class B extends A
{
int number=20;
}
class C extends B
{
int total=number;
void show()
{
System.out.println(super.varOfA);
//System.out.println(super.locOfA); //This is a private variable variable, so it
//won't be accessed from sub class
System.out.println(total);
}
}
public class MLInhert
{
public static void main(String args[])
{
C obj=new C();
obj.show();
}
}
Please let me know if i made any mistake in this answer. Because i'm a beginner here.
Depending on the access specifiers of the variables in the class it is decided which class level variable can be accessed. See the table below:
For more info refer : http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
I am try to find out why below code is giving error, Can anybody explain please.
Here is a class
package abc;
public class A {
public class B {
}
}
Now I am try to create a B class
package xyz;
import abc.*;
public class B extends A{
public static void main(String[] args) {
B b = new B (); // this line gives error. Can you please explain
}
}
Please consider class B extends A is in default package means
import abc.*;
public class B extends A{
public static void main(String[] args) {
B b = new B (); // this line gives error. Can you please explain
// I am try to create "B" class object which extends A
//.. not the B inner class
}
}
Error shows in eclipse is : "No enclosing instance of type A is accessible. Must qualify the allocation with an enclosing instance of type A (e.g. x.new A() where x is an instance of A)."
Given that B extends A, and A contains an inner class B, I suspect there's room for confusion (for both compiler and programmer).
The line:
B b = new B();
is ambiguous. Which B is this ? As pointed out elsewhere, the inner class B needs an containing instance of A, so I suspect you mean the B outer class.
Edit: Your error
"No enclosing instance of type A is accessible. Must qualify the
allocation with an enclosing instance of type A (e.g. x.new A() where
x is an instance of A)."
confirms this. I presume you want the xyz.B and should scope that appropriately.
Try to specify the enclosing scope:
B b = new A.B();
or
B b = new xyz.B();
If you make public class B static, it will work as written.
Otherwise, you cannot make instances of class B from outside an instance of class A, because non-static inner classes require a pointer to their outer class's "this" (within a B, you can write this.A, and that will actually refer to the enclosing A).
When I create the following in Eclipse:
package com.example;
public class A {
class B {
}
}
and
package com.example;
import com.example.A.B;
public class B extends A {
public static void main(String[] args) {
B b = new B();
}
}
As you can see Eclipse imports the class A.B . Without the import the following error is noted:
No enclosing instance of type A is accessible. Must qualify the allocation with an enclosing instance of type A (e.g. x.new A() where x is an instance of A).
The error I get when I try to compile this code (minus the package specs since they seem irrelevant) is "non-static variable this cannot be referenced from a static context". So, the problem is that within the static method main() you are trying to access something non-static, which I guess is the definition of the inner class B.
You actually get the same error if the second outer class has a different name. So the apparent naming conflict is a red herring. Although that itself is a good reason not to use the same name for both classes -- it causes confusion when trying to understand the error.
If I change the declaration of the inner class to be static, the error is resolved.
public class A {
public static class B {
}
}
Some relevant discussion of static vs. non-static nested classes is here.
But this may not be the correct fix. It shows that your code in main() is referencing the B inner class, not the B class that contains the method. Which did you actually want? Obviously, I'd suggest using different names for this two classes to avoid confusion. If what you want in main() is to create an instance of the class that contains that method, then using a unique name for that class will solve your problem.
Your class B extends A has inherited the class A.B and the expression new B() refers to that inner class. Therefore it asks for an enclosing instance. You must either explicitly qualify both your mentions of B with the package name, or, far better, avoid such naming mess in the first place.
I found this solution, through reflection you can create B class(B extends A class) object.
import java.lang.reflect.Method;
import abc.*;
public class B extends A{
public static void main(String[] args) {
//B b = new B(); // this line gives error. Can you please explain
// I am try to create "B" class object which extends A
//.. not the B inner class
try{
Class c = Class.forName("B"); //class B extends A
Method m=c.getMethod("print", null);
m.invoke(c.newInstance(), null);
}catch(Exception e){
e.printStackTrace();
}
}
public void print(){
System.out.println("Printed");
}
}