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.
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.
This question already has answers here:
What is the difference between public, protected, package-private and private in Java?
(30 answers)
Closed 7 years ago.
I just though about it:
if you have class like this:
public class a
{
int x = 5;
//setter & getter
}
you can't access to x from another class unless it is public.
so, that i know, but if it is like that, why do i need to use private?
the x variable cannot be accessed outside of the class without public or in other cases static reserved words.
so, the question(s):
what do i need the private for?
do i have to use the private or it doesn't really matter?
No access specifier is not the same as private.
When you have no access specifier, as in your example, the variable x is accessible in class a, but also in all other classes that are in the same package as class a.
When it is private, it is only accessible in class a, and not in any other class.
See Controlling Access to Members of a Class in Oracle's Java Tutorials.
By leaving out the access modifier, you are relying on the language's default.
For example, in C# class variables default to private.
The most used access modifiers are undoubtedly public and private.
public means you expose your field or method to every other class. This is useful for methods that are necessary to let the class perform its major function(s) and, in some cases, for constants that need to be visible.
private means you hide the member from every other class. This is useful for internal state and functions which other classes must not know about. This enforces the concept of information hiding.
The other modifiers protected and default (when no modifier is mentioned) are intermediate levels of access which can be useful in specific cases.
For example when sub classes need access to a method in the parent (or base) class and you don't want other classes to be able to access it, you can make it protected.
The default access modifier is more restricting than protected and can be used to allow access only from within the same package. This can be useful if a package contains a group of tightly related classes which need to interact among each other via methods which you don't want to expose elsewhere, not even to sub classes outside this package.
Maybe you will also benefit from this article.
this question is already answered in stackoverflow in this link.
There is 4 types of access restrictions in java:
public: the attribute is accessible for all clients
private: the attribute is only accessible from the class, not subclasses.
protected: the attribute is accessible from package and subclasses.
no modifier: the attribute is accessible from the class and package.
It's necessary to declare the scope of accessibility to encapsulate the functionality correctly.
Ok, let me start it with the following example to get a brief example
public class ClassA{
______ static final String MODULE = "[ClassA]";
}
in the blank space, I came across many code snippet it has some times public or protected or private but could not understand the which one is the best and why?.I know protected is best for subclass implementation but then subclass to has MODULE variable.
basically MODULE is used in logging activities like for example
System.out.println(MODULE+"given message");
in-short which is best way to use for accessing?
Like anything, you should give it the strictest access level that makes sense.
If it will only be used inside the class, use private. If it will only be used inside the package, use package access. If it could be used in subclasses, use protected. If it could be used by anyone, use public.
This applies to every class member in every programming language - it is by no means specific to fields named MODULE in Java.
Basically MODULE is used in logging activities...
Then I would suggest to make it private, because it will not be used outside the class (assuming that other classes have similar static constants).
Fairly new to Java, but I'm wondering why package access is considered "more restrictive" than subclass access. That is, every access modifier which provides subclasses with access to a member also provides the whole package with access, and there are modifiers whic provide package access but not subclass access.
Isn't this totally backwards? Let's say I have a class ControlledInstantiation in some package. If I have another class AlsoControlledInstantiation extends ControlledInstantiation, I am unable to call the constructor of ControlledInstantiation unless I set it to protected or public. And if I set it to protected, now any other class in the package can instantiate it as often as it likes. So something which is obliged to be substitutable for its superclass (and, syntactically, is) gets the same or less access to the superclass than something which serves a distinct but related function. It's like telling your child he can't play with your wallet because you wouldn't let your neighbours do it and then letting your neighbours sleep in your house because your kid does.
So I guess I'm asking, what motivated this decision, and how can I get around it?
It may seem backwards at first, but the idea is that a Java package should contain a set of comparatively cohesive classes which are semantically related, and this is reflected in the default package modifier. Then the logic is that if you want to go one step further and allow subclasses from any package to view your members, you can declare them protected. Does it make sense to you that subclasses from foreign packages should be less trusted than any class (whether a subclass or not) from your own package?
Java did in fact once have a private protected modifier which would achieve what you're after, but it was removed, I imagine, because it confused people. I'm not really sure how you could achieve this without relegating each class/subclass pair to its own package. But that's a messy solution which goes against Java's principles and it wouldn't work for inheritance hierarchies of more than two classes anyway.
You are right, this fact is a little bit confusing.
Here are the workarounds I can suggest.
Your example with protected constructor is more relevant for methods. In some cases you can avoid access to protected constructor by package member that are not the subclasses of current class if you mark class as abstract.
If you really wish to avoid access to protected method by package members you can solve this problem at least at runtime using Throwable.getStacktrace():
if(!getClass().isAssignableFrom(
Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
throw new IllegalAccessException(
"This method can be accessed by subclass only");
}
You can seal a package. See the JAR File Specification.
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.