Pros and cons of package private classes in Java?
Asked Answered
L

8

77

I am learning Java recently, and I came across the notion of package-private classes, which is the default if we don't specify anything. But then I realized:

  1. I seldom see the use of package-private class. Is there a reason for this, e.g., it has serious drawbacks, it is redundant, or simply I am not reading enough? Are there strong arguments for/against its usage?

  2. If it is really not useful in most cases, why would it be the default?

  3. In what situation should we use package-private in the real world? I.e., when would it become irreplaceable?

In other words, what are the major pros and cons of the default package-private modifier?

Legislator answered 24/6, 2011 at 16:3 Comment(0)
G
65

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.

Glynas answered 24/6, 2011 at 16:20 Comment(5)
I can see why someone might have said that - the protected modifier is the same as package private except that subclasses are also invited to the party. But it would be wrong to create a subclass relationship (just for access purposes) if one didn't naturally exist. It wouldn't generally make any sense for e.g. an EmailSender class to be a subclass of an DomainObjectFilter class or vice versa. In this situation the method is generally just made public (perhaps with a comment saying that it's not conceptually public...).Glynas
"dump all of the classes for a given module into exactly the same package -- unwieldy" -- Correct, but I've used this approach even in non-trivial cases, like 20-30 classes in package. Anything bigger, of course, is in need for refactoring.Mixon
Couldn't you organize your source files into a directory hierarchy, and then during build, dump them all into the same directory/package before compile? That would give you the organizational structure and the benefit of package private access, correct?Unconscious
@jrahhali you could that, but I'm doubtful that you'll find an IDE that is willing to honor that. I think it would be pretty annoying unless you write an IDE extension that knows what you mean.Wallop
To make use of package private visibility modifier and also to use modules with hierarchy based modifiers, you can use experimental project github.com/odrotbohm/moduliths which works nice for a such scenario,Shrieval
P
20

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.

Psilomelane answered 24/6, 2011 at 17:14 Comment(0)
B
7

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.

Boardinghouse answered 1/7, 2013 at 20:8 Comment(0)
A
4

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".

Archimage answered 10/2, 2015 at 7:5 Comment(0)
S
2

Regarding the question of "why would it be the default,", in this context, the term "default" just means the absence of another qualifier. I guess they could have invented another keyword ("package" was already taken), but they didn't.

In the real world, I use default access for utility classes and abstract classes that I don't want people to call or otherwise use from other packages. Let's say you have an interface and two concrete implementations that extend from some abstract class. You declare your two concrete classes as final because you don't necessarily want people to subclass them (see Effective Java). You also don't want people to monkey around with your abstract class for the same reason. If you use default access for the abstract class, then people only see it if they put their class in your package. It's not bullet proof, but I think it's a reasonable use/illustration of default access. That said, the fact that it does not prevent the details from leaking as private would, i.e. doesn't guarantee anything, means that it's not a particularly useful convention.

Another reason why you haven't see it used more often is that people tend to exclude classes with default access from their javadocs.

Sharpsighted answered 24/6, 2011 at 16:32 Comment(2)
He's not misunderstanding the term "default" he's asking why it is the default access-level. One reason for a default is that something is most often used. There are other reasons, and he's asking for them.Lovash
I'm not sure you're right, but I'm happy to update the response for clarity.Sharpsighted
M
1

1 - Depends on the architecture -Generally if you are writing code just for yourself and on small projects you probably wouldn't use it. In larger projects it can be helpful to ensure that you can control where and how certain methods are called.

2 - Default (I.e. not public/protected/private) is not the same as private - its a 4th state. See Java Access Control

3 - It can make life easier when you're writing libraries that you don't want third parties relying on how you are implementing the underlying code - you just make the API itself public.

Munguia answered 24/6, 2011 at 16:8 Comment(6)
@BZ Isn't the default package private?Legislator
@BZ Which said: If a class has no modifier (the default, also known as package-private). Thanks for the answer, terminology is trivial:)Legislator
Look at the table of permissions - there is a difference between private and no modifier. No modifier anything in the package can read it - so not truly private. This is a HUGE difference from a private class.Munguia
@BZ - the terms "default" and "package private" are often used interchangeably. It looks like you didn't notice that Ziyao was using a compound two-word term, as opposed to just "private".Glynas
@BZ Yes I noticed that, that's why I said package private. Guess I forgot the hyphen :) EDIT: Okay, hyphen added.Legislator
The default is package-private. Nevertheless it is not the same like private.Lehmann
H
-1

"Package Private" its used when you have several packages, and it means, other classes in the same package can access that class or class member as "public", classes in other packages cannot access, its like "private like them."

Headstrong answered 24/6, 2011 at 17:4 Comment(0)
B
-3

Please notice that when you are speaking about classes you have only two options:

  1. public classes
  2. package private classes

The concept of "private class" is meaningless. (Why to make a class that is not used anywhere?!)

So if you have a class for intermediate operations that needn't to be exposed to API users you are supposed to declare it as "package private"

Also when you define many classes in the same source file, only one class is allowed to be public (its name matched the .java file name). If any other class is defined in the same file it must be "package private".

Bacteriostat answered 3/1, 2013 at 15:4 Comment(2)
This answer is at best misleading. A static nested class is an example where the concept of a private class can make sense. See also: stackoverflow.com/a/34551507Selden
This answer isn't that bad. It just should be talking about "top level classes" rather than classes. It doesn't apply to inner classes of any sort, but when you consider top level classes, this is exactly correct.Deviltry

© 2022 - 2024 — McMap. All rights reserved.