5

I have 3 class A, B, C :

package com.training.protectedclass.A; public class A { protected int value; } 

package com.training.protectedclass.B; import com.training.protectedclass.A.A; public class B extends A { public void test() { this.value = 10; A a = new A(); a.value = 12; //Error => The field A.value is not visible } } 

package com.training.protectedclass.C; import com.training.protectedclass.B.B; import com.training.protectedclass.A.A; public class C extends A { public void test() { B b = new B(); b.value = 45; //Error => The field A.value is not visible } } 

When the inherited class exists in different package than the base class, it can't access the protected member of base class. But when all the three class exist in the same package the above errors disappear and the code is compiled without errors.

Can anyone explain me the cause of each error launched in my code above?

Thanks :)

1
  • 3
    It's because C dose not extend B. Visibility is not transitive. Commented Mar 7, 2014 at 23:47

4 Answers 4

3

This is because protected in Java means two things: 1) inherited classes can see protected members that they inherit, and 2) other classes in the same package can see protected members (even if they don't inherit the member).

So in class B you have inherited value and thus you can access it via this.value, but as class A is in another package you can't see a.value. This is because when you call a.value you are accessing a member of a class in another package rather than the inherited version of the field value.

In the case of class C, you can't access any protected member of B because you neither inherit from B nor are in the same package as B.

Sign up to request clarification or add additional context in comments.

Comments

1

The Java Language Specification defines the protected access modifier this way:

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

When you have this.value = 10;, the B object accesses to one of its own members, which is a protected field declared in the superclass. On the other hand, when you have new A().value, the B object tries to access a protected member of an object that it doesn't implement.

Comments

1

Documentation in http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html says this.

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.

But your problem is, you are trying to access a protected member of a different object than this. Check this one out http://bmanolov.free.fr/javaprotection.php

Comments

1

I think JLS 6.6.2.1 gives the answer:

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 qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.

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.

You're accessing the member value in the body of B. Therefore, for applying this clause, S is B, and according to the last paragraph, when you try to access E.value for some expression E, the access is permitted only if the type of E is B or a subclass of B. Since the type is A, which isn't a subclass of B, this condition fails.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.