Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

From the official documentation...

Modifier    Class   Package Subclass    World 
public      Y       Y       Y           Y 
protected   Y       Y       Y           N 
no modifier Y       Y       N           N 
private     Y       N       N           N 

The thing is, I can't remember having a use case where I needed to access protected members from a class within the same package.

What were the reasons behind this implementation?

Edit: To clarify, I'm looking for a specific use case where both a subclass and a class within the same package needs to access a protected field or method.

package some.package;
public class A {
 protected void protectedMethod(){
  // do something
 }
}

package another.package;
public class B extends A{
 public void someMethod(){
  // accessible because B is a subclass of A
  protectedMethod();
 }
} 

package some.package;
public class C {
 public void anotherMethod(){
  // accessible because C is in the same package as A
  protectedMehtod();
 }
}
share|improve this question
add comment

6 Answers

up vote 2 down vote accepted

looking for a specific use case where both a subclass and a class within the same package needs to access a protected field or method...

Well to me, such a use case is rather general than specific, and it stems from my preferences to:

  1. Start with as strict access modifier as possible, resorting to weaker one(s) only later as deemed necessary.
  2. Have unit tests reside in the same package as tested code.

From above, I can start designing for my objects with default access modifiers (I would start with private but that would complicate unit testing):

public class Example {
    public static void main(String [] args) {
        new UnitTest().testDoSomething(new Unit1(), new Unit2());
    }

    static class Unit1 {
        void doSomething() {} // default access
    }
    static class Unit2 {
        void doSomething() {} // default access
    }

    static class UnitTest {
        void testDoSomething(Unit1 unit1, Unit2 unit2) {
            unit1.doSomething();
            unit2.doSomething();
        }
    }
}

Side note in above snippet, Unit1, Unit2 and UnitTest are nested within Example for simplicity of presentation, but in a real project, I would likely have these classes in separate files (and UnitTest even in a separate directory).

Then, when a necessity arises, I would weaken access control from default to protected:

public class ExampleEvolved {
    public static void main(String [] args) {
        new UnitTest().testDoSomething(new Unit1(), new Unit2());
    }

    static class Unit1 {
        protected void doSomething() {} // made protected
    }
    static class Unit2 {
        protected void doSomething() {} // made protected
    }

    static class UnitTest {
        // ---> no changes needed although UnitTest doesn't subclass
        // ...and, hey, if I'd have to subclass... which one of Unit1, Unit2?
        void testDoSomething(Unit1 unit1, Unit2 unit2) {
            unit1.doSomething();
            unit2.doSomething();
        }
    }
}

You see, I can keep unit test code in ExampleEvolved unchanged due to protected methods being accessible from the same package, even though accessing object is not a sub-class.

Less changes needed => safer modification; after all I changed only access modifiers and I did not modify what methods Unit1.doSomething() and Unit2.doSomething() do, so it is only natural to expect unit test code to continue run without modifications.

share|improve this answer
    
thanks, the use case for unit test is good example –  jramoyo Jul 23 '13 at 3:17
add comment

I'd say this has two parts:

  1. The default, "package", access is useful in wide range of cases, because classes are not always good unit of encapsulation. Various composite objects where some object acts as collection of other objects, but the items must not be publicly modifiable, because there are some invariants across the whole collection, so the collection needs to have elevated access to the items. C++ has friends, Java has package access.
  2. Now the "package" access scope is basically independent of the "subclass" (protected) scope. So you'd need additional access specifiers for package only, subclasses only and package and subclasses. The "package" scope is more restricted as set of classes in a package is usually definite while a subclass may appear anywhere. So to keep things simple, Java simply includes the package access in the protected access and does not have extra specifier for subclasses-but-not-package. Though you should almost always think of protected as exactly that.
share|improve this answer
    
Wouldn't it be simpler if protected is subclass only? Honestly, for a long time, I was under the impression that that's the behaviour –  jramoyo Jul 22 '13 at 12:53
    
@jramoyo: No, because you'd still need to make the combined behaviour available somehow, which would mean another specifier. –  Jan Hudec Jul 22 '13 at 14:16
4  
@jramoyo - In C#, protected is class and subclass only, and internal is library/package-wide. It also has protected internal which is the equivalent to Java's protected. –  Bobson Jul 22 '13 at 14:26
    
@Bobson - thanks, the C# implementation seems like a better choice –  jramoyo Jul 23 '13 at 3:20
add comment

A good example that immediately comes to mind is utility classes that are used a lot in the package but you don't want public access (behind-the-scenes-image-loading-from-disk, handle-creation/destruction classes, etc.) instead of making everything [Java's equivalent friend access modifier or idiom in C++] of every other class everything is automatically available.

share|improve this answer
    
Utility classes are more an example of classes that are internal as whole rather than their members. –  Jan Hudec Jul 22 '13 at 11:32
add comment

The use cases for the protected/package access modifier are similar to the ones for friend access modifiers in C++.

One use case is when implementing the Memento pattern.

The memento object needs to access the internal state of an object, to hold it, in order to serve as a checkpoint for undo operations.

Declaring the class in the same package is one of the possible ways to achieve the Memento pattern, since Java has no "friend" access modifier.

share|improve this answer
1  
No, the memento object does not need and should not have any access to the object. It is the object that serializes itself into the memento and deserializes again. And the memento itself is just a dumb property bag. Neither should have more than public access to the other. –  Jan Hudec Jul 22 '13 at 10:56
    
@JanHudec I stated literally "is ->one<- of the possible ways to achieve the Memento pattern". –  user61852 Jul 22 '13 at 12:04
    
And yet another possible way to achieve the Memento pattern is to make everything public. That is, I fail to see your point. –  Thomas Eding Jul 23 '13 at 17:03
add comment

symmetry?

It's rare to need such access, which is why default access is so rarely used. But sometimes frameworks want it for generated code, where wrapper classes are placed in the same package that interact with your classes directly, going to members instead of accessors for performance reasons.. Think GWT.

share|improve this answer
1  
thanks, do you have an example? sounds like that can be accomplished by a "default" accessor rather than "protected" –  jramoyo Jul 22 '13 at 10:18
add comment

Java's encapsulation hierarchy is well defined:

Class -> Package -> Inheritance

"Protected" is just a weaker form of privacy than package-default as decided on by the Java designers. Access to package-default items is restricted to a subset of the entities that are allowed to access protected items.

It makes a lot of sense from a mathematical- and implementation point of view to have your sets of entities that are allowed to access things to be nested. (You couldn't nest your package-access set inside your protected-access set because classes are allowed to inherit from other packages).

It makes sense from a conceptual point of view to have something in java.util to be "friendlier" with another class in the package than something in com.example.foo.bar that is subclassing it. In the former case the classes are likely to be written by the same author, or at least coders from the same organisation.

share|improve this answer
1  
what does it mean "just a weaker form..."? –  gnat Jul 22 '13 at 15:51
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.