In Java, why were protected members made accessible to classes of the same package?

From the official documentation…

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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
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
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>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();
}
}
</code>
<code>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(); } } </code>
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();
 }
}

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):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>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();
}
}
}
</code>
<code>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(); } } } </code>
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>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();
}
}
}
</code>
<code>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(); } } } </code>
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.

0

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.

4

IMHO, this was a bad design decision in Java.

Just speculating, but I think they wanted the access levels to be in a strict progression: private – “package” – protected – public. They didn’t want to have a hierarchy, where some fields would be available to the package but not subclasses, some available to subclasses but not the package, and some both.

Still, in my humble opinion they should have gone the other way: Said that protected is visible to the class and subclasses only, and that package is visible to the class, subclasses, and the package.

I often have data in a class that needs to be accessible to subclasses, but not to the rest of the package. I’m hard pressed to think of a case where the reverse was true. I’ve had a few rare occasions where I’ve had a bundle of interrelated classes that need to share data but which should keep that data safe from outside the bundle. So okay, put them in a package, etc. But I’ve never had a case where I want the package to share data, but I want to keep it from sub-classes. Okay, I can imagine the situation coming up. I suppose if this package is part of a library that might be extended by classes I know nothing about, for much the same reasons I would make data in a class private. But it’s way more common to want to make data available only to the class and its children.

There are lots of things that I keep private between me and my kids and we don’t share with the neighbors. There’s very little that I keep private between me and the neighbors and don’t share with my kids. 🙂

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.

1

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.

3

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.

1

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.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật