I know this applies to many languages, and not just Java, but that is the language I'm most familiar with.
I understand what the modifiers do, and how to use them. I just want to know, why do we need them? Why can't every object be accessible, whether or not it needs to be?
The reason becomes more apparent when you have to maintain a larger project. When a method or variable is public, you have to be careful when you make changes to it, because you never know which parts of the codebase rely on its exact behavior.
But when a variable or method is private, you know that it is not used outside of the class. That means there is a lot less code you have to pay attention to when you make changes.
By making class features private and public, you clearly separate the interface to the outside world from the internals. The less you exposes to the outside world, the more freedom you have with what the internal implementation does.
When you, for example, always make variables private and accessed them through getters and setters, you can later change them from a variable to a computed value, and then even later add caching to the computation for performance reasons. When it would be a public variable, you would have to change code everywhere the variable is used. But when you expose it to the outside world through getters and setters, all other code can keep using the class as if nothing had changed.
Making fields and methods private keeps other classes from improperly depending on the specific details of how a class works. The public interface (and the best case of all, an actual interface) describes how client code should interact with a library based on the semantics of the work being done. The implementer is then free to use whatever appropriate techniques to implement that interface and can make significant behind-the-scenes changes knowing that the client code will keep working.
An everyday example is the Collections group of interfaces. Most of the time, it's not important logically for code to know what particular kind of Set is in use, just that it's a collection that supports certain operations and doesn't have duplicates. This means that a method that accepts a Set<Integer> will work with any Set, including HashSet and ImmutableSet, because the person who wrote the interface wasn't poking around in the implementation's internals.
An example where this breaks down is the unfortunate tendency of some programmers to use packages in the com.sun namespace, especially when using cryptography. Upgrading to a new version of the JRE routinely breaks this code, which would have worked fine if the programmer had used the proper javax.crypto interfaces and factory methods instead of poking around in the JVM internals.
More or less they are used to control who can access your member variables and functions. It's the broader concept of encapsulation at work in Java(http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)).
From the Oracle Docs:
Access level modifiers determine whether other classes can use a
particular field or invoke a particular method. There are two levels
of access control:
At the top level—public, or package-private (no explicit modifier).
At the member level—public, private, protected, or package-private (no
explicit modifier).
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
As to why you should do this:
It has to do with intent of use. It would probably be best described as a design choice that helps guide usage through-out the code-base. By marking something private you are telling other developers that this field or method should not be used outside it's current purpose. It really becomes important on large projects that shuffle developers over time. It helps communicate the purpose & intended uses of classes.
To avoid other classes having direct access to internal members of the class.
This is most useful for avoiding that member variables are mutated in an uncontrolled way (e.g. without proper validation, without notifying listeners, ...).
Another reason to avoid this is that the internal implementation may change at any time but you don't want to break code that uses it.
As others have noted, the concept is called Encapsulation.
Access modifiers are there to set access levels for classes, variables, methods and constructors. This provides an individual with the chance of controlling better the privacy of the application. There are 4 access modifiers.
Modifier | Class | Package | Subclass | World
no modifier:--|----yes----|------yes--------|--------no--------|-----no----|
private:-------|----yes----|-------no--------|--------no--------|-----no----|
public:--------|----yes----|------yes--------|-------yes-------|----yes----|
protected:---|----yes----|------yes--------|-------yes-------|-----no-----|
Regarding your question, we do need and use access modifiers because we need to restrict whom can call our program and in what way.
Also, when it comes to variables if you make something public, that means that I have direct access to it. Therefore, I am allowed to do whatever I want without following your guidelines through your methods.
For example:
public int maxUsers;
public void setMaxUsers(int users) throws IllegalArgumentException{
if(users > 0 && users <= 1000){
maxUsers = users;
}else{
throw new IllegalArgumentException("The users can not be less than 0 or greater than 1000")"
}
}
Imagine your whole program being based on its maxUsers. Since, you give me the right to access that variable directly, I could do this: maxUsers = -15; and not use the setMaxUsers method, which will simply make your program behave in an abnormal way (in the best case).
Explanations
A private member is only accessible within the same class as it is declared.
A member with no access modifier is only accessible within classes in the same package.
or
If a variable is set to protected inside a Class, it will be accessible from its sub classes defined in the same classes or different package only via Inheritance.
A protected member is accessible within all classes in the same package and within subclasses in other packages.
A public member is accessible to all classes (unless it resides in a module that does not export the package it is declared in
Here's a better version of the table. (Future proof with a column for modules.)
Related
How to make a member of a class to be accessible only in subclasses in any packages? Protected is not a solution since it will open the member to other non subclasses classes.
Java does not provide absolute encapsulation. Some amount of discipline is required on the part of the programmer - both the original designer and anyone that uses a published API - to abide by some rules that are outside of the language. Regarding member access, you have identified one such case. What you want is not possible in Java.
Just to put this in broader perspective, I'd point out that even private members can be accessed by other classes if a programmer is willing to go far enough to do it. Calls made via JNI do not have to respect any of the access modifiers. See, e.g., Can a native method call a private method?
Other examples of out-of-language norms include the contract for equals/hashCode, which must be met for classes to behave well with respect to collections but is not enforced at the level of the language.
I understand why you want to do this; however, Java simply does not provide that capability.
You could do abstract class with protected member, and implement it in another packages. Consider you created some lib and design extensability for certain things. Later users of your lib will implement realizations of your class and has access to protected member and in same time not able to create implementation classes in your package. In example FilterReader class, it design for extensibility, after you implement it in somewhere in your code outside java.io package that protected fields and methods will be private to other classes in your package.
What you are trying to achieve ist not possible during to acces control:
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
You may rethink your software design, since yout problem is caused by architecture.
please be more specific in your question for getting further answer.
Solving your problem may cause sideeffects and is not in a OOD manner.
The only way to acces the private member is using an getter method with same visibilty issuses.
While declaring a class as final , we cannot Inheritance this class , my question is why ? - from the java internals perspective.
I assume that the same principle apply to methods and instance as well.
is it somehow related to the class loader as well ? who is actually stopping me from override it?
There's nothing related to the JVM or internals (not really sure what exaclty you mean by that), it's a compile issue simply because you're breaking the rules.
If I think myself as a Java compiler, after parsing the tokens in your code I'm just going to look around for logical errors (semantic analysis) e.g. a circular inheritance scheme. The moment I see someone's attempt at extending a final class, I'm gonna go bazooka. That's it. No need to wake up the big bosses, the JVM or any other internals because the program cannot be correctly compiled in the first place.
If you want to know how the compiler works the way it does internally, think that while the compiler parses your code, it creates and fills some structures internal to itself for the purpose of error-checking and bytecode-translation. Also imagine in a simplified scenario that the final keyword attached to a class just sets a field in one of these structures attached to your class. After syntactic analysis, the compiler goes on with "logical" (semantic) analysis and checks (among other things) if some lunatic tries extending a final class. Even a brute search in an inheritance graph can pull that off. If a class is final and still has children, halt and notify the lunatic. The issue won't get more internal than the compiler.
It is nothing to do with Java internals.
The purpose of declaring a class to be final it to prevent it from being subclassed.
My question was what happening "underground" while declaring final ...
Well ... when a class is declared as final a flag is set in the class file to say this. If you then attempt to load a class that purports to be a subclass of a final class, the classloader will throw a VerifyError exception. The checks are done in the ClassLoader.defineClass(...) methods ... which are also final, so that normal programs can't interfere with them.
This aspect of classfile verification needs to be watertight for Java security reasons. If it wasn't then you could probably cause mayhem in a Java security sandbox by tricking trusted code into using (say) a mutable subtype of String.
The Java compiler also checks that you don't extend a final class, but you could subvert that by (for example) creating ".class" files by hand. Hence the need for load-time checks ...
Who is actually stopping me from override it?
Actually, it is the classloader. See above.
Let's look at it elementally, When you declare a variable as final, you did that because you don't want the value of that variable be changed for any reason afterwards, Right?.
Okay, under the assumption that you agree to that. The same principle is also applicable to classes.
Let's look at it this way: Why will you ever want to inherit a class? Probably because you want get access to the properties of the class and her behaviors (methods), Right? Once you have inherited these properties and behaviors you have the right the modify the accessible behavior to suite your precise need without having to re-implement all other behaviors. This is the value and power of in inheritance.
Hence, declaring a class as final implies that you don't want anyone to modify any behavior of the class. You tries to state that who so ever that will want use your class should use it as IS.
Therefore, any attempt to modify a final class is illogical and should be considered as error.
Eg.
Imaging if someone should be able to inherit your final Authentication class and modifying the actual authentication behavior (method). This should be a security bridge as it might compromise your reasons for setting the class as final.
Hence, it is a design practice.
I hope that make some sense?
consider the class:
class MyClass{
MyOtherClass obj;
//setObj and getObj methods
public void someMethod(){
...
//access to obj needs.
...
}
}
How to right replace
//access to obj needs.
through getter or explicitly?
P.S.
I saw both variants in my expirience.
Personally I would say it depends on the level of "connection" between both classes. If they are in the same package and part of the same "mecanism" (one would have no reason to exist without the other), bypassing accessors is acceptable.
So here we're talking about code in Class MyClass accessing information in an instance of MyOtherClass.
Typically you don't get a choice. If MyOtherClass exposes a getter for a data member, it's unlikely to also expose that data member. If it does (even if the data member is, say, protected but the accessor is public), the design is a bit questionable.
But if you do have the choice, I would use the getter, rather than the exposed data member. It's a bit subjective, but using data members rather than accessors more tightly binds the classes together. In my protected/public example, you'd have more work to do if for any reason you wanted to move MyClass to a different package.
It's worth noting that using the getter is not more expensive in performance terms with a decent JVM (such as the one from Sun). If the code becomes a performance "hotspot" for whatever reason (or possibly even if it doesn't), the JVM's JIT will convert the call to the getter into a direct access anyway (presuming it's a pure getter), so you get the benefit of abstraction at the coding/design-time without the function call overhead at runtime.
To answer this, let's first see why getters and setters were introduced in the first place. It is clear that direct access to data members is simpler.
SOme of the reasons are:
for a better encapsulation, to hide the property implementation from a class user. For example you can internally store a temperature value in C and return it by a getter in F.
for more control over the access. If you want to do something more besides pure getting/setting a piece of data, you would need a method. For example, you might want to log the change of value for audit purpose
methods are much more "interface friendly" than pure data members.
In this case the class itself accesses its own property. Are you sure you want that?
If so, let's see the reasons:
Encapsulation is definitelly not needed, since the class itself accesses its own attributes.
Do you need to somehow control access here? Do you need to do something else, besides get/set? Are there any other possible users of this class?
If all these answers are NO, ans especially if the only user of this class the mentioned method, then go for a simpler option and use direct access, without getters/setters.
If some of the answers is true, just make a simple trade-off and decide.
We have a getter method within a class.
Within the same JAR we want the variable to be accessible with the no-identifier access level, from the same package and subpackages.
Below the access levels from: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Our problem is, how do we stop someone from taking the compiled .JAR, creating a class with the same package namespace definition, and being able to access our variable through the getter?
We thought about getting rid of all getters for the specific variable, and giving the variable value to other classes with setters and constructors, when they pass a reference to themselves. Obviously, they will be final classes. This way all objects needing the variable value have their own private copy.
I'm wondering though if there is a better way?
Access control modifiers (public, private, protected) are not meant as a security tool, but as an OO design tool. They're used to implement OO patterns like encapsulation, inheritance.
Even with no getter whatsoever and a private variable, any Java developer can use reflection to access the variable.
If you want to keep something secret, don't ever put it in a variable of a program executed by anyone. Keep it on your own machines.
- Reflection seems to be the evil here, using which any variable even with private access modifier can be accessed.
- Four access controls like private, default, protected, and public are introduced in Java more as a tool to support the Core Object Oriented Concept like Inheritance, Encapsulation etc...
I get a lot of warnings in eclipse like these:
Variable 'myVariable' must be private and have accessor methods.
I think I get them because I didn't set protectedAllowed manually to true in eclipse. But why is it set to false by default? Shouldn't I use protected attributes?
Theoretically, protected attributes (variables) are an anti-pattern in object-oriented languages. If only subclasses need to access member attributes of its superclass, define the attributes themselves as private and create protected accessor methods (getter and setter). This approach applies the concept of 'information hiding'. There is an alternative solution: define protected immutable (final) member attributes.
Further readings:
Should you ever use protected member variables?
http://www.codinghorror.com/blog/2006/08/properties-vs-public-variables.html
I guess, making everything private is an anti-pattern. Often classes are used in a bunch and as a whole represent encapsulated entity placed in separate package. They do not need to hide something from each other, but this rule enforces hiding for no good reason, increasing clutter and effectively making style (as I understand it) worse. Meanwhile, we often see that every class in package is public. I guess this is much worse, but checkstyle doesn't check that.
Encapsulation exists not only on class level, put also on package, system and so on. And I think that these levels are even more important.
Allowing package access simplifies programming within a package, and reduces boilerplate code. Often times, access is only needed from within the package. Private access forces you to create a lot of nearly useless accessor methods. This actually has the effect of reducing encapsulation and information hiding because a class has to expose internal data/structure application wide instead of just package wide through public accessor methods. The default package visibility also makes testing easier because test classes live in the same package as well (in test dir/tree).