Pros and Cons of Package Private Classes in Java

Pros and cons of package private classes in Java?

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.

When would I use package-private in Java?

I use package-private classes and methods when I want to hide implementation details from users (and other classes) outside the package.

For example if I have an interface and a factory class that creates instances of that interface, I may have the implementation class as a separate file but mark it package-private so others can not use it, nor will it clutter the JavaDoc (if javadoc set to only show public).

If you seal your jar file, package-private methods can also help restrict who can access these methods. If a method is public or protected, subclasses can still see and call that method even if it's in a different package. (Unsealed jars allow anyone to make classes in your packages so they will get access to package-private or protected methods)

Public members in package private class

I do it only for readability, since in this case public members have essentially the same visibility as members without any access modifiers (i.e. package visibility). Is that correct?

Well that depends. Not if you're overriding existing methods (e.g. toString()) or implementing an interface.

If you don't want the method to be used from outside the package, make it package private. If you're happy for it to be used from anywhere, make it public. Or another way to think about it: design your method access so that if someone changed just the class access to make it a public class, you wouldn't want to change the method access too.

Pros and cons of organizing the packages in the Java project

Packages are meant to help you find things.

If they make it more confusing than it is, you're not doing something quite right. If the package structure isn't intuitive, it can actually be harder to find classes than in a flat structure.

There are two basic schools of organising classes into packages as far as I know:

  1. Organising by module first. Here your higher level packages are different modules of the system and you might split it further by function.
  2. Organising by function. Here you organise by function first (e.g. all controller classes in one package, all your data containers in another and so on) and optionally subdivide it by module.

There are pros and cons for both systems, I find them roughlty equal, although I prefer the module approach slightly.

The really important thing is though to follow one system and don't mix it with the other. Don't shoehorn classes into packages they don't belong to and don't be afraid to create a new package if your new class doesn't seem to belong to any of your existing ones.

If a package seems to have grown too large, you might want to split it. But the decision of whether a package should be split or not should be made on whether there is a clear conceptual divide between classes therein and not on numbers. A package with a single class is just as good as a package with thirty classes if it's obvious why they're there.

As for separating interfaces and implementations, first off, I'd probably question the need for them. Ever so often I come across interfaces with only one reasonable implementation, which makes me question their reason to exist. (Sometimes there is a good reason, but often there isn't.)

But if you have multiple implementations for a given interface, then yes, I'd separate them. The interface would be com.foo.Bar and the implementations would be something like com.foo.bars.CrowBar, com.foo.bars.TaskBar for example. Obviously, if your implementations belong to different modules, then you would change it to com.foo.moduleX.bars.CrowBar or com.foo.bars.moduleX.CrowBar, depending on which system you're following.

Re-reading all this, it does sound kind of complicated, but probably the first sentence is the most important: don't follow packaging principles blindly, packages should help you find classes, not hinder you.

Should I use public or package access? Why should I use private for fields?

It's generally a good idea to make all fields private, and to implement getters and setters as needed. That way, you can make sure that the fields aren't used/changed in a way that is unintended. For example, you can add error checking code to your setters, to make sure fields aren't set to values that will break other things. If other classes can set the field directly, you can't prevent that.

If you have a good reason to make a field with package visibility, or public, then of course you can do so, but you have to be aware of what problems that can cause if other people/classes use your fields the wrong way.

It probably doesn't make a lot of difference in your small project, because you know not to set fields to the wrong values, or screw up otherwise - but if other people use your classes or your project grows in size, you will appreciate the fact that the actual fields are private and you can control access via the getters/setters.

Java default access level (package private access). Why it is used for?

A very common pattern for using package-private classes is to create shared implementations of interfaces or shared subclasses of common classes.

Note that the fact of sharing is important here, because inner classes provide a better alternative for hiding class / interface implementations from the caller.

Another common use is for "utility classes", when you wish to share a group of algorithms "horizontally" among different classes, without exposing these algorithms to outside users of your class library. Various argument checkers fall into this category.

Outside classes accessing package-private methods

You could seal the package in your jar file. It's not bullet-proof though.

The main thing is not to rely on access modifiers etc from a security point of view to start with, really. If someone is running the code with unrestricted permissions, they're going to have access to all kinds of things. Access modifiers really just help to stop people from accidentally shooting themselves in the foot.

If someone is willing to put classes in your package to circumvent your encapsulation, they're clearly ignoring your best intentions - I say let 'em get on with it, but don't provide support for that scenario.

Why is the data array in java.util.ArrayList package-private?

When you access a private field from a nested class, the compiler actually generates a synthetic accessor method that is package-visible, and then uses that for the access. It can't access the private member directly, so to avoid that indirection you can make the member package-visible instead.

Here's an answer with more details.



Related Topics



Leave a reply



Submit