Reputation: 77171
I know how package level protection in java works. I read a lot of code (including lots of open source stuff) and no-one seem to be using it. The whole protection level seems slightly faulty to me (I'd have c#'s internal any day of the week).
Are there any legit real-world use-cases that are in common use ?
Edit: A little too late after asking this question I realized I'd forgotten to exclude the "standard" pattern of package protected implementation classes, possibly providing implementations of public interfaces. Everyone uses those, as has been noted several times in the replies. I still think there are a large number of nice replies to this question.
Upvotes: 22
Views: 19777
Reputation: 507005
Are you talking about package-private protection in Java? That's the protection that is in effect by default for class members. It's useful occasionally if you got classes that interact intimately in a way that requires additional information or methods to be visible.
Say you have a Sink class, and several classes can write to that. The Sink has a public method that accepts basic data-types, and a package private method that accepts raw byte arrays. You don't want to make that method public, because you consider it too low-level for its users, but you want to make your other classes (in the package of the Sink) writing to that Sink use it. So you make the method accepting the byte array package private, and classes of your package such as ByteStreamSource could use it. Now, your protection looks like this:
User Code using the package User
------ | -----------------------------|----- package public Interface
| |
Sink <- package priv. iface -> Sources
The package private interface is orthogonal to the public interface established by the public methods. Package private'ness increases encapsulation, because it encourages you not to make public what shouldn't be public. It's similar to the friend
keyword in C++ and the internal
keyword in C#.
Upvotes: 12
Reputation: 490
I am debating many of these issues in my mind currently and this is a good discussion. I have been opting to make all private things private the way they should be, but then I am writing a ton of reflection to unit test privately scoped code. This is, I think the pure OO way to do it. However, I have discovered that it is possible to seal a jar file so that package scope is restricted to inside the module (jar). This, in my mind makes package scope much more palatable. I may be willing to break good encapsulation in exchange for reducing my unit test code to a fraction of what it would be. The thought being that if someone were working in the same library and in the same package that they would be intimate enough with the code base to not access package scope members from outside the class without a reasonable design debate. It is still a tough call. It would be nice to have a friend class type of designation for this type of instance so that my unit test code code access my private code, but not be accessed by other classes. I have just sealed my jar files in this project through maven:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<index>true</index>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<sealed>true</sealed>
</manifestEntries>
</archive>
</configuration>
</plugin>
Now I am debating about pulling out a bunch of reflection code in my unit tests.
I am still on the edge of the debate. Package scope is really quite open, especially if you have many developers bouncing around the code base.
Upvotes: 1
Reputation: 21080
Mostly for Unit testing where source and test files are in the same package, tests can access the internals of the class without exposing it.
Upvotes: 1
Reputation: 70211
There are two good uses for package level visibility (in my experience):
1) Defining "internal" classes in a public API. Commonly you would define your interfaces and core factories as public and the "internal" implementations as package level. Then the public factories can construct the package level implementation classes and return them as instances of the public interfaces. This nicely allows users to only access the stuff they should.
The downside is that you have to have all this stuff in the same package, which almost never is a good idea for any reasonably-sized API. JSR 294/modules/Project Jigsaw in Java 7 will hopefully provide an alternative by specifying a new visibility modifier (module
) that can be used to access classes within a module across packages without making them visible outside the module. You can find an example of how this would work in this article.
2) Unit testing is the other common use case. Frequently you'll see a src tree and a test tree and stuff that would otherwise be private is instead package level so that unit tests in the same (parallel) package are able to access otherwise hidden methods to check or manipulate state.
Upvotes: 33
Reputation:
"I know how package level protection in java works ... and no-one seem to be using it."
What are they using?
Are they making all their classes public?
The Principle of Burden takes two forms.
The strong form states that the burden of transforming a collection of entities is a function of the number of entities transformed. The weak form states that the maximum potential burden of transforming a collection of entities is a function of the maximum potential number of entities transformed.
The International Organisation for Standardization defines encapsulation as the property that the information contained in an object is accessible only through interactions at the interfaces supported by the object.
At a higher level of abstraction, program units, too, may be encapsulated within subsystems, whereby the information contained in the subsystem is accessible only through public program units contained within the subsystem.
The burden of creating or modifying any software system is a function of the number of program units created or modified.
Program units that depend on a particular, modified program unit have a higher probability of being impacted than program units that do not depend on the modified program unit.
The maximum potential burden an modified program unit can impose is the impacting of all program units that depend on it.
Reducing the dependencies on an modified program unit therefore reduces the probability that its update will impact other program units and so reduces the maximum potential burden that that program unit can impose.
Reducing the maximum potential number of dependencies between all program units in a system therefore reduces the probability that an impact to a particular program unit will cause updates to other program units, and thus reduces the maximum potential burden of all updates.
Encapsulation theory shows how to use encapsulation to reduce the maximum potential number of dependencies between all program units.
Encapsulation theory therefore shows how to use encapsulation to mitigate the weak form of the Principle of Burden.
In Java, making a class package private is one of the key mechanisms for reducing the maximum potential number of dependencies in a system and so reducing the maximum possible burden of any software modification to that system.
Yet you mention that this is not used in the code you read.
That sounds ... odd.
Upvotes: 0
Reputation: 21628
Another use of default protection in Java is for performance.
Inner classes are allowed to access private members of their containing class, but this is implemented through obfuscated accessor methods. Before the JIT compiler optimizes this away (or in environments without a JIT such as J2ME) this causes a small performance hit. Declaring the needed methods with default protection eliminates the need for these accessor method calls, but doesn't require making the members fully public.
Keep in mind that this is only important where performance is known to be critical, and where you can't count on the JVM fixing the issue for you. But at least it doesn't really harm readability/maintainability as much as many other micro-optimizations.
Upvotes: 3
Reputation: 625087
I know Java veterans of 5-10+ years who don't realize that protected
implies package private acess. This alone, for me, makes package private an horrific language feature. Personally I don't think there is any justifiable reason to use package private anyway. Let's consider the use cases:
Compare this to protected methods, which are entirely justifiable when designing classes for extension. I've seen cases where programmers inadvertently use protected methods in unrelated classes in the same package just because they come up on auto-completion lists.
And there is absolutely no way to prevent this.
C# has a better access system in that protected doesn't imply internal access. But I consider this--along with a mutable Date class--to be pretty huge flaws.
Upvotes: 1
Reputation: 276
The reason why nobody uses package level access it is probably a psychological effect. Every java introduction preaches encapsulation, which is understood as declaring all fields private. Private access is very often too narrow, so a public getter/setter must be added. This pattern is then repeated throughout the whole codebase: private fields and public methods everywhere. Ironically, the pattern subverts encapsulation, as the whole implementation is essentially nailed down by the getter/setter pairs.
A class is primarily the unit of memory allocation and in many cases that is just too small to provide a meaningful interface to the rest of the program. It is a much better idea to use packages as the unit of encapsulation and focus on giving them well defined public interfaces.
Superpackages in 1.7 might change the rules of the game.
Upvotes: 2
Reputation: 54475
In my opinion, package-private (default) access for methods and fields is useless. In fact, it's worse than useless, it's harmful since it's typically used to provide access to some member that ought to be private but isn't for reasons of convenience.
However, package-private classes are useful. You may want to provide an implementation of an interface using a package-private class. A factory method might be declared to return an object that implements a given interface. In this situation, it is not important to know which class is providing the implementation for the interface. By making the class package-private, it is not part of the public API and therefore can be modified or replaced in future versions.
In Oak, the language that later became Java, there were only 3 access levels.
If I were redesigning Java now, I would get rid of the current default (package-private) and make private the default. A private class would be one that is private within its enclosing scope (the package), which would work exactly how package-private classes work already and be more consistent with the use of 'private' for members.
Upvotes: 2
Reputation: 62769
In general, Default/Package protection can be used to to make "Public" classes and variables more restricted.
You only export a few methods from your class (if you're a good programmer) by tagging them public while keeping as much as possible private.
Package protection allows you to only export a few classes from your package, keeping the rest private.
In theory it's a great idea, in practice you almost never see it.
Upvotes: 0
Reputation: 89749
I think that in principle package level protection makes a lot of sense. It allows you to create something close to a module (a package) but only expose the core classes.
For example, many of my projects work with public interfaces and "hidden" classes that implement them. Users use factories, and receive a reference to the interface which corresponds to a "hidden" concrete implementation. With package protection I should be, in theory, able to only expose the interfaces and the factory.
Unfortunately, because package protection does not apply to subpackages, it doesn't really fit the way that I work. I like using other packages and in particular subpackages for my "internal" stuff (in the same way that Eclipse is organized). As a result, my package cannot access package-level protected things in the subpackage. I do wish that this would be changed one day.
Upvotes: 5
Reputation: 7388
Nowadays, packages are often used to model "software components", i.e. a package is a group of classes somehow related. Since "public" methods define the external interface of a software component, and "private" methods/members are implementation details of a class, the default "package" visibility amounts to component-internal methods.
An analogy might be "friend" methods in C++.
Upvotes: 1
Reputation: 112366
Default protexction, ie "package" protection means it's private to the package, but can "see" anything that's not private to a class in the package. One use is for helper classes for the package; say you have a class that manages a pooled resource you don't want to make visible, you could put it in a default-protection class. Now it can be used by everything in the package, and it can access any protected internals of the other classes, but it's not part of the visible package to a user.
Upvotes: 3
Reputation: 14643
I have objects that need access to one another. Within the package, they can call these protected methods,but when someone tries to access these protected methods, they are disallowed.
In my opinion this is a basic protection mechanism, and a hierarchy of protection would be a nice feature.
Upvotes: 1
Reputation: 191925
It can be used for implementation classes, for one thing. For example, EnumSet
is an abstract class, and no implementing classes are shown in the docs. Why? Because there are two implementing classes--one for enums with 64 or fewer elements, and one for 65 or more--and you don't really need to know which one you're using. In fact, you don't even need to know that there's more than one implementation. In fact, you don't even need to know that EnumSet
is abstract--you just need to know that you can call one of the static methods and get a Set
back.
In this case, private internal classes might have sufficed (although unwieldy, especially for large classes). But sometimes other classes in a package would need access to such implementation details. protected
could work, but then they would be open to subclasses also.
In short, it covers an area of encapsulation that is not handled by the other three levels of protection.
Upvotes: 8