Fine points of protection
In the article Some Sentences about Java I wrote that “Protected methods and fields can be used from classes in the same package (so far the same as package private) and in addition to that it can be used from other classes that extend the class containing the protected field or method.”
Although the statement above is true it may not reveal the whole truth and I believe it deserves a new article.
When you have a private X (method, field, class, interface, constructor) in a class you can use that X from within the top level class. The use means, as described in the previous article, that X can be accessed in the instance “this
” and in other instances so long as long the code accessing is in the same top level class where X is.
If you remove the private
keyword in front of X then you extend the visibility to package level. You can use X inside the package the same way as you could use it before from within the class when it was private.
If we still go further one step and insert the keyword protected
in front of X it will became visible from classes that extend the class where X is declared but can NOT be accessed the SAME WAY as private X from within the class or package private from within the same package. Since protected
is extending the visibility of X from package private, protected X can still be used the same way within the package, but not the same way outside of it.
The difference is that you can only access a protected X in the code that is extending the functionality of X.
The above is not a precise definition. The Java Language Specification that I cite here in this blog many times details that in chapter 6.6.2 What can I say about that? Precise, complete but may not be easy or entertaining to read, which may also be true for this article, but since you are reading it I assume that you find it entertaining, educating or you have some very specific reason to read it.
While you are in the same package as the class declaring X you can access X on other instances. We can have some simple classes to demonstrate this. First of all we can have a root class that we will extend:
package a; public class A { protected void protectedMethod(A a) { } }
We have the class ‘B’ which extends ‘A’ and is in the same package.
package a; import a.A; public class B extends A { @Override protected void protectedMethod(A a) { a.protectedMethod(this); super.protectedMethod(this); } }
If we move/copy the class ‘B’ to another package, like here:
package b; import a.A; public class B extends A { @Override protected void protectedMethod(A a) { a.protectedMethod(this); super.protectedMethod(this); } }
then the line 6 will not compile. When it was in the previous package the compiler allowed it to access the method, because package protection made it possible. No matter what implementation instance the argument ‘a’ is to the method, they are in the same package. In case of ‘b.B’ class package protection does not allow access and because the actual object instance that we store in the method argument ‘a’ may be an instance of a class that ‘b.B’ is not extending it can not access it. It can be an instance for example of the class:
package c; import a.A; public class C extends A { }
What you can do is:
- Override the method in the child class or
- call the parents method using the keyword
super
.
And generally this is really all you can do with protected methods outside of their package.
Reference: | Fine points of protection from our JCG partner Peter Verhas at the Java Deep blog. |