views:

50

answers:

3

I learned that a class can be either public or package-private (the last value is the default one). A field of a class also can be either public or package-private. These "statuses" have the same meaning. If something is package-private it is visible only within the same package. It is public it is visible from everywhere (from any package).

What is not clear to me is how these statuses interplay. In particular I have interest in the following two cases:

  1. The class is public but its field is package private. Will be this field visible only from within the package?

  2. The class is package-private and it has a public field. Where will be sing this field?

In general I do not understand why we bother if a class is public or package-private if, in any case, for any individual component of a class (field and methods) we indicate if it is public or package-private.

+4  A: 

The most restrictive visibility applies. The answers to your questions are:

  1. Yes.
  2. Package only.

public fields in package classes usually don't make much sense.

There are some subtleties: a private field in a private nested class can be read by the enclosing class (though this causes some performance loss due to the implicit addition of synthetic accessors).

There's a short note on visibility in Sun's tutorial. Also refer to the section on nested classes.

Edit: For your interest, reflection also allows to tamper with visibilities.

Xr
Xr, but in the first case the field visibility override the class visibility. The field is package-private and class is public, and as a result the field is visible only from the "native" package.
Roman
Correct. Actually, it's the most restrictive that applies. I messed up the first sentence (fixed it), but the rest of my answer still holds.
Xr
+1  A: 
  1. If the class is public then all members of the class are 'potentially' visible. But as you say, the field will only be visible within the package.

  2. If the class is not visible then how will you reference the field? So yes it will be restricted to the package only.

Of course it is worth noting that most of the time you shouldn't be using public fields unless they're constants.

I didn't understand your final point when I first read it, but I think you're asking why it is worth setting a restrictive class access modifier when you can just restrict access to the methods. One reason why you cannot rely on the fields/methods to provide the restriction is that an extending class (potentially in another package) may increase the visibility of the method. But if they cannot see the class to extend it then you're safe(r).

Tom Castle
So, if a class is "public" than all field are potentially public, and the field will be really public if we use the "public" modifier in front of these field. If a class is package-private, than field's modifier do not have any sense (no mater what field modifier we use, this field always be package-private).
Roman
Yes for the "potentially public" part. No for the package-private thing. In that case, "protected" and "private" still keep their meaning.
Xr
That's right. In the second case the field could be package-private or private of course.
Tom Castle
I don't think it can be protected can it? Because protected is less restrictive than default.
Tom Castle
Suppose a package-private class "Parent" has a protected field "foo". A public class "Sub" from the same package extends it. It has access to foo. A class "SubSub" from another package extends Sub. It has access to foo, too, even though foo belongs to a package-private class. Sub sort of increased the visibility of foo without ever explicitly touching its definition.
Xr
A: 

You can think of the the visibility as a hierarchy. You must be allowed to see the class before you can see any of its members or functions. With that in mind, your two scenarios resolve as:

  1. Yes, a class within the same package can see package private fields in a public class.
  2. Only classes in the same package can see public members and functions in a package private class.

If you are writing APIs that you expect others to use, it's a good idea to use package private to hide classes that are around to help with your design, but do not contribute to the API.

sutlermb