48

What is the reason that in Java, a member with a "protected" modifier can not only be accessed by the same class and by subclasses, but also by everyone in the same package?

I am wondering about language design reasons, not actual applications (e.g., testing)

Uri
  • 88,451
  • 51
  • 221
  • 321
  • 13
    +1 Frankly I want know why as well. It always struck me as one of the dumbest design decisions in Java. – cletus May 24 '09 at 02:28
  • 3
    @cletus : So longer I think about it so more I come to the conclusion that “package private” was the not well thought out idea. For “package private” to actual work and offer any kind of real protection, packages would need to be compiled within a single compilation unit. And one should not be able to enhance them later. – Martin Dec 20 '13 at 09:18

6 Answers6

26

This design is based on the idea that the package is the appropriate unit, maintained and released by one internally consistent team; inheritance relationships have much less to do with who's maintaining and releasing what when.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 2
    Thanks for the answer. Of course does not actually work since no one stops you from distribution a package over several jars — and with it over several teams. So it is a other nice idea not fully thought out. Something Java is full of. – Martin Dec 20 '13 at 08:29
25

The modifiers are well-described at http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html. From there we see this figure.

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

From this the reason for the design decision is obvious: it's to have a nice symmetric matrix.

Glenn
  • 6,455
  • 4
  • 33
  • 42
  • @Michael Myers: Well, no, it would not be symmetric anyway. It's symmetric for a reason. – Glenn Dec 21 '10 at 22:40
  • 1
    If you put an N instead of a Y at the `protected` -> Package intersection, it's still symmetric. Just not as pretty. – Michael Myers Dec 21 '10 at 23:00
  • @MichaelMyers: I don't think the Matrix is symmetric either way. But what is currently is: All **Y** above (and on) the diagonal line and all **N** below. – Martin Dec 20 '13 at 08:40
16

In Java 1.0 there was a fifth access modifier: private protected. This was protected without the default access. Apparently it never actually worked properly and was dropped in 1.1. So it looks like claims the protected is defined the way it is for total ordering appear to be spurious. (Edit: It does appear that at least one of the reasons the fifth access modifier was removed in 1.1 was that the lack of total ordering interfered with the overload selection rules.) The module access modifier in Java 7 has a few design questions in this area.

Given that it was thought that it would be a good idea for the default access modifier for members to be "package private", it seems reasonable that protected should have be at least this level of access. For my money, protected doesn't pay its way in the language at all.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • I've never heard of that one, but I got into Java at 1.1... Thanks! – Uri May 24 '09 at 04:32
  • 1
    And since no one stops you from adding more classes to a package in a different jar file “package private” is not all that private either. As it is: Anything apart from private and public is more or less a hint to the programmer but no real protection. – Martin Dec 20 '13 at 08:34
  • A very late question, but do you have a source on this? I would like to now in more detail how and why this failed back then. – Pieter De Bie Dec 04 '18 at 09:28
  • 1
    @PieterDeBie That was from memory. I upgraded the internal project I was working on from 1.0 to 1.1 around 22 years ago. bugs.sun.com gives me only '"private protected" was eliminated to simplify other parts of the specification - for example, rules regarding overriding require access protections to be comparable (that is, strictly weaker or stronger than one another.) ' – Tom Hawtin - tackline Dec 04 '18 at 17:07
  • @Martin You can mark jars as "sealed" in the manifest, which prevents any additions. Of course the jar itself could be modified - including the class files. Unless you sign the jar, in which case you can't add any classes to the same *runtime* package with a different signature (assuming the signature is verified). Also any classes from a different class loader will be in a different *runtime* package. – Tom Hawtin - tackline Dec 04 '18 at 17:13
7

Basically it has to do with the view of a package as an api controlled unit (hence the recommendation to start your package with your domain name - guaranteed global uniqueness), so visibility grows from private -> package-private -> protected -> public. If protected weren't an increase over package-private, rather a different type of visibility, there would have to be some way to combine the two types of visibility when needed.

Yishai
  • 90,445
  • 31
  • 189
  • 263
  • 2
    But no one stops you from adding a new class to an already exiting package. So “package private” and with it “protected” is only a recommendation to the programmers. Both don't offer any real protection from malicious/desperate programmers wanting/needing to call the method. — “protected” like in C++ would at least force the use of a subclass — but in Java you don't even need to do that. – Martin Dec 20 '13 at 09:10
1

Given progressive levels of access, private, package, protected and public, it would be unnecessarily limiting if it went protected then package since that would force me to allow subclasses access in order to grant other members of the same package. Yet, intuitively, it should be that other classes in the same package are more trustworthy than other classes "out there". So protected is between package and public in that it allows a wider exposure of access.

I think the basic reason relies on the intuition that there's a basic level of "trust" between classes in the same package; you can reasonably expect them to do the right thing with each other - in most cases the package will be the responsibility of a single engineer or team so there should be a consistent harmony of design.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
  • 1
    That is the theory. But in praxis this would only be true when a package would need to be compiled in a single compilation unit and could not be enhanced outside. But that is not the case and so, with the aid of a slim delegate class, any “package private” method can be made public. A hint to the programmer but not a true protection. – Martin Dec 20 '13 at 08:56
  • @martin: only if you publish the package without sealing it, which capability addresses this particular problem. – Lawrence Dol Dec 22 '13 at 02:54
  • “sealing the package” — never heard of it but sounds interesting. **Tell me more!** (a few words to help me google the details it is sufficient) – Martin Dec 22 '13 at 06:55
  • 1
    Found it on my own: http://docs.oracle.com/javase/tutorial/deployment/jar/sealman.html — yes interesting. Should be on default ;-) . – Martin Dec 22 '13 at 07:01
0

Java does follow its design principles on itself. What happens when you try to reduce/narrow the scope of public method in a subclass ? one gets an error. Java scope modifiers levels follow : private < (default) < protected < public

All class in package are supposed to be friendly because they work together. To make a member available in package it is defined in default scope.

A subclass may reside outside the package, following scope levels again : private < (default) < protected < public - We can not narrow down the scope. Protected is broader scope than default so Java does not contradicts its own guidelines. Thus, a protected member will be available in default scope. Also : class < package < Project.

Please do not limit modifiers to only visibility, but inheritance, structure are also in work at same time and add them to picture as well. If this was true : private < protected < (default) < public. then all sub classes would have to reside in same package, then why you need to inherit you can access everything as default scope is there at applicable at package level. Default scope would have lost its value and so does inheritance.

jbhardwaj
  • 379
  • 3
  • 8