Related
The java syntax allows member fields/methods of local classes to have access modifiers. But they have no effect at all. This seems to apply to anonymous classes as well.
This feels very counterintuitive. Is this behavior specified in the JLS?
Code:
class Foo {
public static void main(String[] args) {
class Bar {
private int a = 1;
protected int b = 2;
public int c = 3;
}
var bar = new Bar();
System.out.println(bar.a); // works for private a
System.out.println(bar.b); // works for protected b
System.out.println(bar.c); // works for public c
}
}
Yes. Just in the section about access modifiers - there is no separate section about 'the meaning of access modifiers specifically in the context of local classes' for the same reason there is no section about 'the meaning of access modifiers specifically when there's a full moon out' - there's nothing that changes here.
JLS §6.6.1 covers everything you need to determine exactly what happens (and conclude that they, indeed, have no effect here). I've intentionally picked JLS8, because 9+ muddies the waters somewhat due to module scope stuff.
A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:
Emphasis mine: The type is not accessible for any and all code, except the code inside the very method you've declared your local class in. That trivially means that access modifiers are completely irrelevant here for all code outside of your method - they can't even access Bar, therefore the accessibility of field a is moot.
Thus, we can restrict determining what each access modifier would do solely to '... to the code that tries to access it, which must therefore live in this very method, because anywhere else its trivially inaccessible due to the type being inaccessible'. Then:
public
Trivially, the code in the method can access public things.
nothing (package private)
Trivially, code in the method is in the same package as the local class is, by definition - package statements can only exist at the compilation unit level and these things are neccessarily in the same unit. Thus, yes, code in the method can access package private things.
protected
... is a superset of package private, therefore, yes, code in the method can access protected things.
private
From the JLS 6.6.1:
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
By definition the local class is not a top-level class; the job of 'walk upwards in the syntax tree until you hit a top-level class', when applied to a local class, leads to the same answer, guaranteed, as when you apply it to the other code in the method the local class is in. Thus, yes, you can access private things.
Thus...
for all 4 access levels, the answer is the exact same thing: Yeah, you can. Hence, access modifiers are irrelevant. This isn't called out in the JLS because that's the result of applying the rules.
Guesses about intent
I did not personally design java-the-language. So, these are merely guesses:
Explicitly making any specification about the nature of access modifiers in local classes means the JLS is longer than it needs to be - the above behaviour is sensible enough (what else would you want here? Let's say that you wanted private stuff to be inaccessible - why? That's not how private works anywhere else in java, why should local classes be the one exception?)
Disallowing them entirely could be worthwhile, saving some 'room' in the mental model and the compiler specs, perhaps. However, that's problematic - local classes can implement things and extend something - and that may require certain access level (you cannot override a method and reduce its access level). The spec would then also have to say that for local classes the 'cannot reduce access level' rule is waived, and then would complicate everything for no reason.
The reason And example of why it is useful to be able to specify access modifiers is to allow local and anonymous classes to implement interfaces, which require the implementing methods to be public, or to allow local and anonymous classes to extend other classes and override public methods. (You cannot make the access specifier of a method more restrictive when you override it).
For example:
class Foo {
public static void main(String[] args) {
Comparator<String> byLength = new Comparator<String>() {
// Need to make this method public because the method
// in interface Comparator is public
#Override
public int compare(String o1, String o2) {
return Integer.compare(o1.length(), o2.length());
}
};
// ...
}
}
For other use cases, the Java language designers probably simply didn't bother to add extra rules to explicitly forbid access modifiers. It would just have made the rules of the language more complicated, and the ability to specify access modifiers here isn't useful, but doesn't do any harm either.
Although, this is a very basic code, it seems there is something fundamentally flawed in Java, or the JVM used by the Eclipse IDE I have used to run the code.
The code runs even though it should not (I think)! The code in A.java simply displays "Hello, I am A!"
Here it is:
import java.lang.*;
import java.util.*;
class A {
private void methodA() {System.out.println("Hello, I am A!");}
public static void main(String[] args) {
A a = new A();
a.methodA(); }
}
I do not understand why, after creating an instance of class A, main() succeeds in running a private method of class A on that instance. Yes, the main method belongs to class A, but it is not accessing the private method from inside the current object in the context of the "this" reference. In fact, since it is a static method, it cannot access non-static members from within the class. Instead of main(), a non-static member method could have invoked methodA() from inside only. But that is another issue since I have not defined any non-static second method.
Now that the inside-view is talked about, let's come back to the point, the outside-view. As you can see, main() attempts to invoke methodA from outside the object and succeeds! Why isn't private getting treated as private?
I am pulling my hair....
Anyone, please reply...
Yes, the main method belongs to class A, but it is not accessing the private method from inside the current object in the context of the "this" reference.
That doesn't matter. That's just not the model of accessibility that Java uses. What's important is the class in which the code is written, not whether it's accessing members in the same object.
This is very useful, as otherwise (for example) it would be impossible to implement an equals method using private members of both classes.
This may not be how you would have chosen to specify the language, but it is how Java is specified. See JLS 6.6.1 for details of accessibility. In particular:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Note that protected access is slightly odd here - a protected instance member of class SuperClass can only be accessed within code in SubClass via an expression of either SubClass or a further subclass. But it still doesn't have to be "the same" object.
private modifer
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself.
private means "private to the class". Not "private to the instance".
That's what allows implementing things like static factory methods calling private constructors, or equals() or compareTo() methods comparing private fields of objects of the same class, or copy constructors, etc.
Private members of enclosing classes are also accessible from inner classes of this enclosing class, and vice-versa.
After the technically correct answers here's my two cents why I think it is quite reasonable to implement private that way:
As I see it the main reason that private methods and attributes exists is "implementation hiding". You are declaring "Don't use this method from outside my class(!), since it might change or disapear anytime I like". So it makes sense to disallow access from outside the class. But if I'm accessing it from another object of the same class I and make any implementation changes I'm well aware of the changes and the accesses of the private members and can act accordingly.
Another thing to think about:
If class B extends class A, then any B-object also is an A-object, but it can't access the private A-methods. Why would that be if private methods were private to the object?
I am relatively new to java and I did some reading about private and public acccess modifiers. I would like to eliminate any confusion once and forall in this topic because I feel like I don't have the best grasp on it.
Access modifiers in variables
Please correct me if I am wrong, a variable is public on default. If the access modifier is set to public or just not set at all, than other classes from the same project can access the integer and/or modify it. If it is private than it is not visible to the outside and cannot be accessed by classes outside the one in which it was created.
Accesss modifiers in classes
Access modifiers in classes, I don't seem to fully understand. As far as my understanding, if I call a private method from method that is not in the same class, than it will not work. If it is public than it will?
Is there anything I am missing or don't understand correctly?
I appreciate help in this regard.
Please correct me if I am wrong, a variable is public on default.
You're wrong. Assuming you mean fields, by default, they have "package" access, which can't be expressed explicitly. Local variables have no concept of access control - they only exist within the context of a method anyway, so can't be referred to from anywhere else.
If the access modifier is set to public or just not set at all, than other classes from the same project can access the integer and/or modify it.
If it's set public, then any code can access it.
If it's default (package) access, then any code in the same package can access it.
Access modifiers in classes, I don't seem to fully understand. As far as my understanding, if I call a private method from method that is not in the same class, than it will not work. If it is public than it will?
That's pretty much right, yes.
I suggest you read the Java tutorial on all of this, and consult the language spec section 6.6 for more details.
Here's a good doc on the subject.
There are four access levels:
private: Only that class (not even descendants) can access.
protected: Only that class and its descendants and classes in the same package can access.
package-private (no specifier)--only classes in the same package can access--even subclasses that are not in the same package cannot.
public: Everything can access.
For for both classes member variables and methods, the default access is package private.
You can find information about the 4 modifiers here on Oracles website.
If you do not specify the modifier, it is said to be on default, which means only any code in the same package can access it.
If it's set public, then any code in any package can access it.
Actually in Java there are four different access modifiers, private, public, protected and package specific. "Please correct me if I am wrong, a variable is public on default" - you are wrong here a variable if not declared differently has a package related access. If it is set to public then it can be modified by other classes even outside of the original package. This website - http://javapapers.com/core-java/access-modifiers-in-java-explain/ - can provide you useful hints. Actually it is very easy once you read a bit more on OO concepts such as Encapsulation. Then you will understand the purpose of access modifiers (to ensure data integerity).
Java provides a number of access modifiers to set access levels for classes, variables, methods and constructors. The four access levels are:
Default : Visible to the package. No modifiers are needed.
Private : Visible to the class only.
Public : Visible to the world. All classes and packages.
Protected : Visible to the package and all subclasses.
If no access modifier is specified by the programmer, default access modifier is used.
Access Modifiers:
Public - {Can access anywhere in the project}
Private - {Can access only inside the class}
Protected - {Can access within the package and sub classes}
Default - {can access within the package}
Non-Access Modifiers:
Static - {for creating class variable and method}
Final - {for creating finalized class, variable and method}
Abstract - {for creating abstract method and class}
Synchronized - {for threads}
To learn more follow this link
private and public java access specifiers.in java,private access specifiers it specifies the access.private is like own family property that can uses only which family belongs.that means inside the class,method and variable can be used.
public is like government properties that means every one can access the properties without any need of tokens
private and public java access specifiers.in java,private access specifiers it specifies the access.
private is like own family property that can uses only which family
belongs.that means inside the class,method and variable can be used
.
public is like government properties that means every one can access
the properties without any need of tokens
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'm working my way through an exercise to understand Java, and basically I need to merge the functionality of two classes into one app.
I'm stuck on one area though - the referencing of objects across classes.
What I have done is set up a gui in one class (test1), and this has a textfield in ie.
chatLine = new JTextField();
in another class(test2), I was planning on leaving all the functionality in there and referencing the various gui elements set up in test1 - like this test1.chatLine
I understand this level of referencing, I tested this by setting up a test method in the test2 class
public static void testpass() {
test1.testfield.setText("hello");
}
I'm trying to understand how to implement the more complex functionality in test2 class though, specifically this existing code;
test1.chatLine.addActionListener(new ActionAdapter() {
public void actionPerformed(ActionEvent e) {
String s = Game.chatLine.getText();
if (!s.equals("")) {
appendToChatBox("OUTGOING: " + s + "\n");
Game.chatLine.selectAll();
// Send the string
sendString(s);
}
}
});
This is the bit I'm stuck on, if I should be able to do this - as it's failing on the compile, can I add the actionadapter stuff to the gui element thats sat in test1, but do this from test2 - I'm wondering if I'm trying to do something that's not possible.
Hope this makes sense, I'm pretty confused over this - I'm trying to understand how the scope and referencing works.
Ideally what i'm trying to achieve is one class that has all the main stuff in, the gui etc, then all the related functionality in the other class, and target the first class's gui elements with the results etc.
Any thoughts greatly appreciated.
If you can access chatLine in the first place, you can call its (public) methods, including addActionListener. To access chatLine directly, you need to make it public, and if you want to make it specific to the class (as opposed to a different chatLine for each instance of the class), it needs to be static.
Note, however, that it's often desirable to not make variables public. An important reason for having classes and objects in the first place is encapsulation. You might consider hiding the implementation inside the classes by making it private and only providing higher level public methods to access what is needed, e.g. do not expose the "raw" JTextField but rather expose the functionality you use it to provide.
I'm not clear on whether chatLine is a local variable, an instance variable, or a static variable. Any of these things could be the source of your compile error, which you didn't specify -- what's the error?
If it's an instance or static variable, it can be made visible from anywhere by making it public. This doesn't mean that's a good idea.
At least, it should be private and exposed via a getChatLine() method.
Even then, there's some question about whether this design is the right one, but at least you'd be doing it right at a compiler level and basic data encapsulation level.
Generally speaking everything in Java is referenced but primitive types.
The so called visibility of objects is another matter:
public scoped members are visible
to all
'Package Friendly' members (those
that have no scope explicitly
mentioned) are visible to all abjects
belonging to the same package
protected scoped members are both
'Package Friendly' and visible to all
inheriting class objects
Finally, private scoped members are
visible only to the object itself
[Objects from the same class can view
each other's private members (as far
as I can recall)]
Now,
an inner static class can access its
enclosing class's static members.
A 'normal' inner class (without the
static modifier) can access its
enclosing class's static members
and enclosing object's instance
members - that goes as well to
anonymous inner class.
Finally any chain of method/field calls as below is valid (but ugly) as long as no part of the chain 'references' a null:
myObj.getThatObject().somePublicField.doSomthing().activate().someOtherPublicField
One recommendation though is not to declare members as public...