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:
The class is public but its field is package private. Will be this field visible only from within the package?
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.
The most restrictive visibility applies. The answers to your questions are:
Yes.
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.
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.
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).
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:
Yes, a class within the same package can see package private fields in a public class.
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.
Related
I have a Java class that is about 4,000 lines long (lots of methods). This class then uses about 200 small classes that only it needs, so another 4,000 lines of code.
If this was C# I would put those other in a partial class file so different file, but they would remain private nested classes only visible to the parent class.
Is there a way to do this in Java? I'm not asking for some methods to be in a distinct file, but for private nested classes to be in a distinct file.
thanks - dave
You can't make a class private to only another class while putting it in a different file.
Use no class access modifier
What you can do is put the classes in separate files with no access modifiers (omit "public"), which will make them package-private, i.e. visible only within its own package. See also the official Access Control tutorial.
UtilClasses.java:
package OurPackage;
class UtilClass1
{
}
class UtilClass2
{
}
MainClass.java:
package OurPackage;
public class MainClass
{
UtilClass1 iAmAUtilClass;
}
Use interfaces or inheritance
You can also achieve something similar with either interfaces or inheritance, by omitting the access modifier from the nested class. This would also be package-private, but this might be preferable to the above in some circumstances, since it avoids having all the nested classes at the top level.
BaseInterface.java:
package OurPackage;
interface BaseInterface
{
class UtilClass1
{
}
}
MainClass.java:
package OurPackage;
public class MainClass implements BaseInterface
{
UtilClass1 iAmAUtilClass;
}
You can also use a base class instead of an interface and extend that with roughly the same effect.
You don't need to implement BaseInterface gain access to its nested classes, but, if you don't, you'd need to use BaseClass.UtilClass1 instead of just UtilClass1.
Inner private classes can't be "extracted" and still be visible only to one particular class. One solution is already mentioned in the comments: Create a package that contains the "main" class and all the previously inner classes and make the inner classes package visible. This would also allow you to create unit tests testing for the correct functionalities of the inner classes, which is something that is most likely currently not happening simply because the inner classes can't be "reached" by a unit test at the moment.
Concepts like declaring "friendships" between classes like in C++ don't exist in Java.
You can replace the inner classes with top-level ones, but you'll have to rewrite a lot of things by hand that the compiler auto-wires for you with the inner-class relationship. To the Virtual Machine, an inner class is nothing special, it's just another class in the same package as the outer class with a fancy name. But the compiler creates a lot of helper constructs under the hood, that you have to reconstruct by hand (or have some refactoring tool do that for you):
The inner class can refer to the outer this instance, by prefixing it with the outer class name. You need to pass the outer this into your inner constructor and store it in a field like outerThis to get access.
In the source code, you can call the outer-class methods directly. You need to rewrite it like outerThis.method(). The same applies to fields.
For private outer methods and fields to become accessible, the compiler creates bridge constructs for you. You have to either change access modifiers or create package-private bridge methods yourself.
In the end, you'll have the former inner classes at least package-visible and being more verbose than the original ones, but on the other hand you'll get better isolation and testability.
I just started reading a Java book and wondered; which access specifier is the default one, if none is specified?
The default visibility is known as “package-private” (though you can't use this explicitly), which means the field will be accessible from inside the same package to which the class belongs.
As mdma pointed out, it isn't true for interface members though, for which the default is "public".
See Java's Access Specifiers
The default specifier depends upon context.
For classes, and interface declarations, the default is package private. This falls between protected and private, allowing only classes in the same package access. (protected is like this, but also allowing access to subclasses outside of the package.)
class MyClass // package private
{
int field; // package private field
void calc() { // package private method
}
}
For interface members (fields and methods), the default access is public. But note that the interface declaration itself defaults to package private.
interface MyInterface // package private
{
int field1; // static final public
void method1(); // public abstract
}
If we then have the declaration
public interface MyInterface2 extends MyInterface
{
}
Classes using MyInterface2 can then see field1 and method1 from the super interface, because they are public, even though they cannot see the declaration of MyInterface itself.
If no access specifier is given, it's package-level access (there is no explicit specifier for this) for classes and class members. Interface methods are implicitly public.
The default visibility (no keyword) is package which means that it will be available to every class that is located in the same package.
Interesting side note is that protected doesn't limit visibility to the subclasses but also to the other classes in the same package
It depends on what the thing is.
Top-level types (that is, classes, enums, interfaces, and annotation types not declared inside another type) are package-private by default. (JLS §6.6.1)
In classes, all members (that means fields, methods, and nested type declarations) and constructors are package-private by default. (JLS §6.6.1)
When a class has no explicitly declared constructor, the compiler inserts a default zero-argument constructor which has the same access specifier as the class. (JLS §8.8.9) The default constructor is commonly misstated as always being public, but in rare cases that's not equivalent.
In enums, constructors are private by default. Indeed, enum contructors must be private, and it is an error to specify them as public or protected. Enum constants are always public, and do not permit any access specifier. Other members of enums are package-private by default. (JLS §8.9)
In interfaces and annotation types, all members (again, that means fields, methods, and nested type declarations) are public by default. Indeed, members of interfaces and annotation types must be public, and it is an error to specify them as private or protected. (JLS §9.3 to 9.5)
Local classes are named classes declared inside a method, constructor, or initializer block. They are scoped to the {..} block in which they are declared and do not permit any access specifier. (JLS §14.3) Using reflection, you can instantiate local classes from elsewhere, and they are package-private, although I'm not sure if that detail is in the JLS.
Anonymous classes are custom classes created with new which specify a class body directly in the expression. (JLS §15.9.5) Their syntax does not permit any access specifier. Using reflection, you can instantiate anonymous classes from elsewhere, and both they and their generated constructors are are package-private, although I'm not sure if that detail is in the JLS.
Instance and static initializer blocks do not have access specifiers at the language level (JLS §8.6 & 8.7), but static initializer blocks are implemented as a method named <clinit> (JVMS §2.9), so the method must, internally, have some access specifier. I examined classes compiled by javac and by Eclipse's compiler using a hex editor and found that both generate the method as package-private. However, you can't call <clinit>() within the language because the < and > characters are invalid in a method name, and the reflection methods are hardwired to deny its existence, so effectively its access specifier is no access. The method can only be called by the VM, during class initialization. Instance initializer blocks are not compiled as separate methods; their code is copied into each constructor, so they can't be accessed individually, even by reflection.
default is a keyword that is used as an access modifier for methods and variables.
Using this access modifier will make your class, variable, method or constructor acessible from own class or package, it will be also is set if no access modifier is present.
Access Levels
Modifier Class Package Subclass EveryWhere
public Y Y Y Y
protected Y Y Y N
default Y Y N N
private Y N N N
if you use a default in a interface you will be able to implement a method there like this exemple
public interface Computer {
default void Start() {
throw new UnsupportedOperationException("Error");
}
}
However it will only works from the 8 Java version
Official Documentation
Access Modifiers in Java
See here for more details. The default is none of private/public/protected, but a completely different access specification. It's not widely used, and I prefer to be much more specific in my access definitions.
the default access specifier is package.Classes can access the members of other classes in the same package.but outside the package it appears as private
Here is a quote about package level visibility from an interview with James Gosling, the creator of Java:
Bill Venners: Java has four access levels. The default is package. I
have always wondered if making package access default was convenient
because the three keywords that people from C++ already knew about
were private, protected, and public. Or if you had some particular
reason that you felt package access should be the default.
James Gosling: A package is generally a set of things that are kind of
written together. So generically I could have done one of two things.
One was force you always to put in a keyword that gives you the
domain. Or I could have had a default value. And then the question is,
what makes a sensible default? And I tend to go for what is the least
dangerous thing.
So public would have been a really bad thing to make the default.
Private would probably have been a bad thing to make a default, if
only because people actually don't write private methods that often.
And same thing with protected. And in looking at a bunch of code that
I had, I decided that the most common thing that was reasonably safe
was in the package. And C++ didn't have a keyword for that, because
they didn't have a notion of packages.
But I liked it rather than the friends notion, because with friends
you kind of have to enumerate who all of your friends are, and so if
you add a new class to a package, then you generally end up having to
go to all of the classes in that package and update their friends,
which I had always found to be a complete pain in the butt.
But the friends list itself causes sort of a versioning problem. And
so there was this notion of a friendly class. And the nice thing that
I was making that the default -- I'll solve the problem so what should
the keyword be?
For a while there actually was a friendly keyword. But because all the
others start with "P," it was "phriendly" with a "PH." But that was
only in there for maybe a day.
http://www.artima.com/intv/gosling2P.html
Update Java 8 usage of default keyword:
As many others have noted The default visibility (no keyword)
the field will be accessible from inside the same package to which the
class belongs.
Not to be confused with the new Java 8 feature (Default Methods) that allows an interface to provide an implementation when its labeled with the default keyword.
See: Access modifiers
There is an access modifier called "default" in JAVA, which allows direct instance creation of that entity only within that package.
Here is a useful link:
Java Access Modifiers/Specifiers
First of all let me say one thing there is no such term as "Access specifier" in java. We should call everything as "Modifiers". As we know that final, static, synchronised, volatile.... are called as modifiers, even Public, private, protected, default, abstract should also be called as modifiers . Default is such a modifiers where physical existence is not there but no modifiers is placed then it should be treated as default modifiers.
To justify this take one example:
public class Simple{
public static void main(String args[]){
System.out.println("Hello Java");
}
}
Output will be: Hello Java
Now change public to private and see what compiler error you get:
It says "Modifier private is not allowed here"
What conclusion is someone can be wrong or some tutorial can be wrong but compiler cannot be wrong.
So we can say there is no term access specifier in java everything is modifiers.
I have been reading Thinking in Java from Bruce Eckel these days, when comes to the Access Control chapter, it says if a java file has two or more classes, except the public one, others can not be private (that would make it inaccessible to anyone but the class) or protected.
But I have seen a lot of popular java libraries and open source projects did have used private to decorate these kind of classes.
So is it because the book too theoretical or any reason else?
the original text (page 231, forth edition)
Note that a class can not be private (that would make it inaccessible to anyone but the class) or protected. So you have only two choices for class acess: package acces or public. If you don`t want anyone else to have access to that class, you can make all the constructors private, thereby preventing anyone but you, inside a static member of the class, form creating an object of that class.
The statement is only true for top-level (non-nested) classes. Nested classes may be private. That's because top-level classes have visibility into private nested classes (including the private members of a nested class), and vice versa. They may also be protected, meaning subclasses of the enclosing class, even in another package, can reference them.
Note that this isn't unique to Java files that declare more than one top-level class. private and protected are not allowed on any top-level class declaration.
Are classes private or public by default in Java and C++?
Java:
By default, the classes visibility is package private, i.e. only visible for classes in the same package.
C++:
The class has no visibility defined like in Java. They are visible if you included them to the compilation unit.
In Java, a top-level class is either public or non-public. There is no "private". You can only use the public keyword or leave it off. If you leave it off it is non-public, i.e., visible only to other classes in the same package.
A nested class, that is, a class inside of another class, can be made public, package-private, protected, or private, just like any other class member. The default (i.e., the one with no modifier) is package-private, visible only to classes in the same package.
EDIT: Forgot the C++ answer, so see (and upvote) #zeller's answer. :)
According to §6.6.1 of the JLS,
If a top level class or interface type is not declared public, then it may be accessed only from within the package in which it is declared.
So, a Java class is by default package-private.
This doesn't apply to C++, however. A class lacks visibility -- only its members can have access control. See §11 of the C++11 standard for information on member access control. Here's an excerpt from ¶1...
A member of a class can be
private; that is, its name can be used only by members and friends of the class in which it is declared.
protected; that is, its name can be used only by members and friends of the class in which it is
declared, by classes derived from that class, and by their friends (see 11.4).
public; that is, its name can be used anywhere without access restriction.
Java
By default Java class is package-private.
C++
In C++ there is no visibility defined like Java.
In java, do we really have to do that in order our variable or method to be public? For example:
void aaa() {
...
}
or
public void aaa() {
...
}
If it is a must, why?
Well that's not a variable, that's a method - but yes, you have to do that to make a method public. If you don't, it has the default package access, and won't be accessible from other packages. You should judge for yourself whether any particular method you write should be accessible only within the same class (make it private) to subclasses (make it protected), to the package (leave the default; you can't state package access explicitly, unfortunately) or to everything (make it public).
(This is a slight simplification of the access modifiers, but it's a start.)
As for why this is the case - typically you should limit visibility so that your type only exposes the methods which really make sense for the concept it's trying to encapsulate. You may have many more private methods which are implementation-specific, and which the outside world shouldn't know or care about.
You can ommmit access level modifier anywhere except near main method. There it must be set to public.
Not putting a modifier is actually different than public, private, or protected.
With no modifier, only the class itself and any class in the same package can access the attribute.
Learn more here: In Java, difference between default, public, protected, and private
The two methods are different: the first has package visibility, while the second one is public.
The difference is that package-visible methods appear public only to methods inside the same package, while public methods are visible to all methods, inside and outside the package.
So the answer to your question depends on your intent: if your method is truly part of your component's interface, make it private; if it is designed for use only inside the package, keep it at the default package visibility.
In your first example, the method will be package scoped -- i.e. only things in the same package can use it. So yes, you do need to declare public fields/methods/classes as such, otherwise they will have package scope.
The default is package private.
If you want public or anything else, you must specify it.
Method can be accessed by the class itself, other classes within the same package, but not outside of the package, and not by sub-classes.
See chart at bottom:
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
I think it is assuming public in Java, so it is not really required.If you start having public, protected, and private throw in the mix in a single class, it is easier to see what scope the method may have.