On pages 219 - 220 in the book 'Certified Associate Java SE 8 Programmer I' by Jeanne Boyarsky and Scott Selikoff, there is a code sample that challenges you to determine what will and will not compile based on package access:
All of the errors are in School.java:
Line 7: "The field Classroom.globalKey is not visible". Since when is a field with default access not visible to another package? default != private, right?
Line 8: "The constructor Classroom(int, String) is not visible". Even though the roomNumber field has a private access modifier, and the teacherName field has a protected access modifier, we are still importing everything from the my.school package on line 2, so why is visibility still an issue? Or do import statements only make the classes themselves visible, and not necessarily the variables inside of them?
Sam Peterson wrote:Or do import statements only make the classes themselves visible, and not necessarily the variables inside of them?
No, import statements have nothing at all to do with visibility. The purpose of an import statement to save the programmer from having to type fully qualified names all the time. For example in your second class there, if you didn't have the import statement then line 8 would have to be
The gory details are all in the JLS (=Java® Language specification). It says that a protected member or constructor is accessible in code responsible for the implementation of the object. So an instance method or constructor or instance field declaration (I think) can use that protected member or constructor, but a static method can't. Nor can other classes in a different package access a protected member or constructor in a class inhering it from a superclass in a different package. There are more restrictions; see the JLS link.
It may be bad practice to use a protected member or constructor method in a constructor.
A derived class D can only access a protected member of a base class B from a different package if it's done through an object reference with formal type D or a subclass of D:
The formal type of the local variable b is Base, and since Base is not Derived or a subclass of Derived, Derived is not allowed to access the protected members of Base through b.
What could be the reason for this seemingly ridiculous rule? Well, imagine that you had a type MyCollection with a protected field size, and you were implementing classes MyList and MySet that extend MyCollection. You wouldn't want to be able to access the size field of a MyList from a MySet, because those classes really don't have any business being all up in each other's internals. If MyList could access protected field size through a reference of type MyCollection, it could inadvertently be modifying a MySet object.
Thank you for the correction, which was obvious in your earlier example. About calling methods, I was just trying to warn people against calling methods left right and centre from constructors....and didn't do it very well.