Pros and cons of package private classes in Java?
Apart from encapsulation, one of the main advantages of using package-private classes is that they do not appear in the javadoc of your project. So if you use some helper classes which have no other use but to help your public classes do something clients need, it makes sense to make them package private as you want to keep things as simple as possible for users of the library.
As an example, you can have a look at a library that I have developed. The javadoc only contains 5 interfaces and 12 classes although the source code has a lot more. But what is hidden is mostly internal layers that provide no added-value for a client (typically all the abstract base classes are hidden).
There are also many examples in the JDK.
One nice thing about package-private is that you can use it to give access to methods you would otherwise consider private to unit test classes. The downside of course being that other classes in the package could call it when they really shouldn't.
The package-private access level is more restrictive than protected
: protected attributes and methods can still be accessed by simply subclassing a class. Protected members are (or may be) intended for inheritance while package-private members are not.
Package-private members are often used so multilpe classes inside a package can access implementation-specific attributes or (utility) methods.
Good examples to this are the package-private constructor of String
and the StringBuilder.value
char array:
/*
* Package private constructor which shares value array for speed.
* this constructor is always expected to be called with share==true.
* a separate constructor is needed because we already have a public
* String(char[]) constructor that makes a copy of the given char[].
*/
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
So classes inside the java.lang
package can efficiently create new Strings
if the content is already present in a char[]
without compromising security. You cannot do this from your application because if you could, you would have access (reference) to the internal char array of a String
which is immutable (reflection not counted!).
In StringBuilder
(or rather AbstractStringBuilder
where the implementation comes from) the char array holding the current value char[] value
and an accessor method to this char[] getValue()
are also package-private so various utility methods of String
like contentEquals(StringBuffer sb)
and contentEquals(CharSequence cs)
can utilize this for efficiency and faster comparisons without exposing the internal char array to the "world".
The short answer is - it's a slightly wider form of private.
I'll assume that you're familiar with the distinction between public
and private
, and why it's generally good practice to make methods and variables private
if they're going to be used solely internally to the class in question.
Well, as an extension to that - if you're thinking about creating your software in a modular way, you might think about a public interface to your module, which will have multiple classes inside it collaborating between themselves. In this context it makes perfect sense to make methods public
if they're going to be called by consumers; private
if they're internal to a class; and package private
if they're used to call between classes in this module, i.e. it's an implementation detail of your module (as seen by public callers) but spans several classes.
This is seldom used in practice, because the package system turns out to not be so useful for this sort of thing. You'd have to dump all of the classes for a given module into exactly the same package, which for anything non-trivial is going to get a bit unwieldy. So the idea is great - make a method accessible to just a handful of "nearby" classes, as a slightly wider private
- but the restrictions on how you define that set of classes means it's rarely used/useful.