tags:

views:

2244

answers:

14

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.

+8  A: 

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 ocassionally 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 serveral 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#.

Johannes Schaub - litb
+4  A: 

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.

Michael Myers
+1  A: 

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.

Milhous
Module-level access perhaps? I think probably coming in JDK7.
Tom Hawtin - tackline
I would assume so.
Milhous
Internal in C# means "public within the assembly = public within the jar file"
krosenvold
+3  A: 

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.

Charlie Martin
+1  A: 

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

mfx
+1  A: 

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.

Darron
Changing visibility scope for the sake of an unproven performance gain is always a bad idea.
Software Monkey
I'd say "usually" a bad idea. If you are coding for a low performance platform (phone?) it may be necessary.
Darron
Can you really document an instance of this causing a performance issue? I don't think it's impossible, but this seems really unlikely to be an issue to me.
Alex Miller
@Darron: I said "unproven performance gain".
Software Monkey
+2  A: 

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.

Uri
I agree with having some sort of package-and-subpackages visibility modifier; I have been forced to make methods public for subpackages because that was less evil than moving the subpackage classes into the parent package.
Software Monkey
And I have one package where a set of 6 or so classes belong in a subpackage, but the methods they need absolutely must not be public - this is one instance where I really wish I could explicitly declare another package as friend to the main one.
Software Monkey
A: 

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.

Bill K
I think the final statement is incorrect; I have many examples of legitimate package protected methods. This is esp. true when the package fulfills a tightly cohesive function (as opposed to being a collection of related classes).
Software Monkey
I've written quite a few as well--but I've almost never seen them in the wild. I agree that they are a great idea.
Bill K
+1  A: 

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.

Dan Dyer
interesting link, thanks. but they seem to praise the current 4 access levels. in oak, there were public, protected and package private (the default), apparently (hearing of oak the first time :)). java left the default where it was, and introduced private as a more restrictive one.
Johannes Schaub - litb
Yes, Oak definitely didn't get it right because it lacked a proper 'private'.
Dan Dyer
-1 for the claim that package access is useless, saved at the last second with a countering +1 for wishing private were the default and inferring that one should habitually declare things as private and open them up only when required.
Software Monkey
@Software Monkey, in what situations do you use package-visible methods (not classes)? Every time I've used a package visible method, it's always felt like a hack.
Dan Dyer
+1  A: 

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.

Stefan Tannenbaum
A: 

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:

  • Package private classes: use inner classes. Another poster suggested there is a (small) performance penalty for inner classes vs package private classes but, to me, that's not a good reason for bad design. Package private and inner classes I consider to be implementation details and, as such, I think it's better to "hide" them as inner classes;
  • Package private data members: I can see no reason for these at all; and
  • Package private methods: these are pretty much the equivalent of C++ friend methods. C++ friends had one good raison d'etre and that was to externalize operator overloading outside of the class, which allowed the first argument to be something other than the class itself. In Java, there is no such use case, which just leaves doing an end-run around encapsulation and abstraction.

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.

cletus
-1 for what is, in my opinion, a patently absurd claim. Package access has huge applicability for a package which fulfills a single cohesive public purpose - say a pattern matching package like regex.
Software Monkey
@Software Monkey I'm not sure his claim is absurd ;) Cletus arguments for the code style used by a lot of apache stuff. I don't LIKE the 3000 line class-files this leads to, but it hides the private stuff a lot better. I think it's a lot nicer with many package protected classes.
krosenvold
A: 

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

+8  A: 

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.

Alex Miller
+1  A: 

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.

Sathish