and why the same, can be used with inner classes?
public class Hello {
class inner{ // this class can use any modifier
}
}
Java only allows top level classes / interfaces to be public or package.
Section 7.6 of the JLS states (Top Level Type Declarations):
By default, the top level types declared in a package are accessible
only within the compilation units of that package, but a type may be
declared to be public to grant access to the type from code in other
packages (§6.6, §8.1.1, §9.1.1).
Section 9.1.1 of the JLS of interface modifiers states:
The access modifiers protected and private pertain only to member
interfaces within a directly enclosing class or enum declaration
(§8.5.1).
The modifier static pertains only to member interfaces (§8.5.1, §9.5),
not to top level interfaces (§7.6).
I hope this is clear.
Nested classes can be static, private, protected, package-local, or public
Top level classes are not;
static as this wouldn't mean anything. static for a nest class means it doesn't hold a reference to an outer class, but if you are the outer class it doesn't have a use.
private classes cannot be access from another class file, so a private top level class couldn't be accessed.
protected classes could potentially be used from sub classes, but making the class abstract is clearer. IMHO.
Private top-level class does not make any sense because you can't access it from anywhere.
Protected means to access class within the same package or subclass of the outer class.Since there isn't package inheritance in java then protected classes also does not make any sense.
When we declare method/parameter as static, then we can access it without creating an instance of object.Because static member belongs to the class as a whole, not the instance of class or object. Since there isn't enclosing class for top-level classes, it is meaningless to define top-level classes as static.
All types of access modifiers can be used on all types of classs (except anonymous classes).
Classes with other types of modifiers, will give access, exactly like a method.
static won't work, since it means that it belongs to some other class, that is never true for an outer class.
Related
For a class being static, it is required it to be not a top level class. Since all classes belong to Object class which is the superior of all classes, then why can't we create a class with static keyword? Why is static classes allowed only in nested scenario.
All the classes in Java (transitively) extend Object, they are not inner classes inside it.
static wouldn't mean anything for top level classes, and therefore is forbidden. For inner classes, static means the same thing it means for other members (such as data members and methods) - the inner class belongs to the outer class, not to a specific instance of it.
My interviewer asked me about inner classes.. After explaining him everything he stopped me on my one sentence- if inner classes can access private members of outer class then doesn't it violate privacy?
I was unable to answer it.
From a JVM perspective, yes, an inner class accessing a private member of the outer class violates privacy.
But, from a Java perspective, no, it does not violate privacy.
JVM perspective
The Java Virtual Machine Specification, section 5.4.4. Access Control says:
A field or method R is accessible to a class or interface D if and only if any of the following is true:
[...]
R is private and is declared in D.
So, the JVM will only allow private members to be accessed from code in the same class, i.e. a nested class cannot access private members of the outer class.
Java perspective
The Java Language Specification, section 6.6.1. Determining Accessibility says:
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:
[...]
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.
So, a private member in a top-level class and/or nested class is accessible from code anywhere within that top-level class. Since nested classes by definition occur within the body of the enclosing top-level class, code in nested classes can access private members of the outer class.
Synthetic access
To solve the discrepancy, the Java compiler creates hidden (synthetic) methods for allowing "private" access between closely related classes, i.e. between a top-level class and all its nested classes.
This is an internal trick of the compiler and is not really documented in the specifications. JVMS, section 4.7.8. The Synthetic Attribute says:
[...] A class member that does not appear in the source code must be marked using a Synthetic attribute, or else it must have its ACC_SYNTHETIC flag set. [...]
The Synthetic attribute was introduced in JDK 1.1 to support nested classes and interfaces.
For more information, do a web search for java synthetic accessor.
See also: Synthetic accessor method warning
Answer is No as inner class is part of the outer class, just like other variable and methods are
All private variable/method of a class can be accessed inside all methods of the same class. An inner class is a special case where an instance of InnerClass can exist only within an instance of OuterClass. Hence it has direct access to the methods and fields of its enclosing instance.
The answer is NO, because inner class has internal link to the outer class and inner class does not exists without concrecte instance of outer class.
But if you add static to the inner class declaration, it means the it does not have link to the outer class and this is the same, when you declare class in it's own file.
That is all, clear and simple.
If you look closely at statement#1 and #2, you will find that the only difference between them is of one extra object (of inner class) that gets created in #1, rest everything access-wise is exactly same.
There is no violation because somewhere you're intentionally leaving the door open through some form of access specifier like public or protected. Inner class doesn't act (or is not capable to act) as a workaround in there, so no violation absolutely.
public class AccessPrivateMemberThruInnerClass {
private int getUniqueId() {
return 101;
}
private class AnInnerClass {
public int getParentID() {
return getUniqueId(); // invokes private method inside a public method.
}
}
public int getUniqueIdForce() {
return getUniqueId(); // invokes private method inside a public method.
}
public AnInnerClass getInnerClassObject(){
return new AnInnerClass();
}
public static void main(String[] args) {
AccessPrivateMemberThruInnerClass obj = new AccessPrivateMemberThruInnerClass();
System.out.println(obj.getInnerClassObject().getParentID()); // #1
System.out.println(obj.getUniqueIdForce()); // #2
}
}
Answer : No inner class does not voilate the privacy of outer class.
Explanation : All instance methods defined in a class are able to access the private or not private fields and methods defined in the class. This happens as all the instance methods and fields belong to the current object of the class.
Same is true for any inner (non static) class, it has an implicit reference of outerclass current object.
This is the reason as why you can only create the object of inner (non static) class with the help of an object of outer class. If you create the object of inner class inside any instance method of outer class then it is created with the help of implicit current object reference of the outer class.
If you have inner class which is static, then it does not has implicit reference to current object of outer class. Any instance field or method belong to an Object of the class. Hence static inner class can not access any private or non private instance field or method of outer class.
You can set reference of outer container class object explicitly and then it can acess. Now with the help of this explicitly set reference of outer class you can access the private Fields and methods.
So now lets modify the question as why inner static class with an explicit reference of outer class can acess and modify private methods and fields ?
Answer is related to our decision for having such design. The intention of defining any entity within the scope of a class is belongingness. If belongingness is missing then you should reconsider your decision lf making the class as inner (static or non static). Inner classes should be made when we wish to encapsulate a sub responsibility to an entity. This makes the related responsibility still cohesive.
Iterator is a part of any Collection and hence it is inner class. Custom AsyncTask class defined in custom Activity class in android is often made as private static (with weak reference of outer class activity) to prevwnt activity leak as the intention is to modify the fields which are private.
P.S : Afer compiler compiles the code it generates separate files for inner class and you can refer the link to understand as how the interaction of fields of one class being accessible to other class happens when other class is defined as inner class
https://stackoverflow.com/a/24312109/504133 . Actually synthetic getters and setters are injected in the code by compiler so as nested static class can access private fields using these. But still this is backend task done by langauge tools.
import java.util.*;
public class NewTreeSet2{
void count(){
for (int x=0; x<7; x++,x++){
System.out.print(" " + x);
}
}
}
protected class NewTreeSet extends NewTreeSet2{
public static void main(String [] args){
NewTreeSet2 t = new NewTreeSet2();
t.count();
}
}
Here, I cannot make the NewTreeSet sub class as protected. Why is this? I am not trying to accomplish anything, this is only for my understanding of the access specifiers.
public is the only access-modifier that can explicitly be applied to a top level class in Java. The protected modifier in case of a class can only be applied to inner classes.
Section 8.1.1 of the Java language specification says this :
The access modifiers protected and private pertain only to member classes within a directly enclosing class declaration
So why can't top level classes be marked as protected? The purpose of protected access modifier in Java is to add restrictions on the access to a member of a class. Since a top level class is not a member of any class, the protected access modifier does not make sense for top level classes. Inner classes can be marked as protected because they are indeed members of a class. The same rules apply for private as well.
A class definition itself can only be public or package-private. Public classes must be defined in their own file and the filename must be the class name.
The documentation doesn't say anything about why there are only two access modifiers for the top level, but one might say that it is logical:
The protected access modifier makes sure only instances of the same or a child class can access the subject. Polymorphism is not applicable to classes, only to instances of classes. Thus the protected keyword there doesn't make sense.
If you want to protect the construction of objects, you should specify an access modifier to your constructor.
"Why can't we have the 'protected' modifier for a top-level class".
Assume it's allowed to use protected modifier for a class. Then what will happen, it will be visible to all the classes in the same package which is the same behavior what a default (package-level) access class will possess. Additionally this 'protected' class should be visible to all the subclasses outside package also. But unfortunately you would not be able to create any subclass of this class outside the package because this class itself will not be visible outside the package. Hence without the subclass specific behavior, this 'protected' class will be exactly same as a package-level or default access class. So, there is absolutely no need of 'protected' modifier for classes and hence, not permissible as well.
---This was posted in a different forum, by B Verma, found this answer according to which all of you said. It was really helpful, thank you.
http://www.coderanch.com/t/585021/java/java/Protected-access-modifier-class-level
Consider this piece of code:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private int privateField;
private void privateMethod() {};
};
}
There is an anonymous class that has a private member field and a private member method. It has been successfully compiled.
Then consider this one:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private class PrivateInnerClass {}
};
}
There is an anonymous class that has a private member class. However...
javac said: error: modifier private not allowed here
Eclipse said: Illegal modifier for the local class PrivateInnerClass; only abstract or final is permitted Really local class?
What? Why anonymous classes cannot have public, protected or private(hereinafter referred to as those) member classes while they can have those member fields and methods? Confused, I looked into JLS. Because of what Eclipse stated, I looked into local classes first:
14.3. Local Class Declarations
A local class is a nested class (§8) that is not a member of any class and that has a name (§6.2, §6.7).
It is a compile-time error if a local class declaration contains any of the access modifiers public, protected, or private (§6.6), or the modifier static (§8.1.1).
So local class cannot have those modifiers. But PrivateInnerClass is a member of the anonymous Cloneable, so it is not a local class and is still able to have those modifiers.
Then I looked into class modifiers:
8.1.1. Class Modifiers
The access modifier public (§6.6) pertains only to top level classes (§7.6) and to member classes (§8.5), not to local classes (§14.3) or anonymous classes (§15.9.5).
The access modifiers protected and private (§6.6) pertain only to member classes within a directly enclosing class or enum declaration (§8.5).
But PrivateInnerClass is a member class, and it's within a directly enclosing class, the anonymous Cloneable, so it can still have those modifiers on theory. I looked into other parts as well, but I still couldn't find relevant provisions.
So which part of Java Language Specification said a member class of an anonymous class cannot have those modifier?
Extra Note 1: Some answer argued about member classes and local classes, so I made a test that can conclude that (unless modifiers matters):
The anonymous Cloneable is neither a member class nor a local class.
The PrivateInnerClass is a member class, but not a local class.
The following is my test code:
public class TopLevelClass {
Cloneable c = new Cloneable() {
class PrivateInnerClass {}
};
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c1 = Class.forName("TopLevelClass$1");
Class<?> c2 = Class.forName("TopLevelClass$1$PrivateInnerClass");
System.out.println(c1.isMemberClass()); // false
System.out.println(c1.isLocalClass()); // false
System.out.println(c2.isMemberClass()); // true
System.out.println(c2.isLocalClass()); // false
}
}
Extra Note 2:
Review the declaration of a normal class (JLS §8.1):
NormalClassDeclaration:
ClassModifiersopt class Identifier TypeParametersopt
Superopt Interfacesopt ClassBody
In my understanding, when the Identifier class is an XXX class, what §8.1.1 stated is restricting the modifier of Identifier, not the modifiers in other declarations in ClassBody of Identifier. Otherwise, anonymous classes even cannot have those member fields and methods.
Any answer, especially which disagree with Extra Note 2, must point out why those member fields and methods are allowed.
Extra Note 3: If you think there isn't such part of JLS, you'll still need to give a reliable document to explain why those member classes are forbidden and why those member fields and methods are allowed.
You have:
Top-Level Class TopLevelClass : not nested (hence is named, not local, not anonymous)
Second-Level Class, a no-name class that extends Clonable and is a not a member of any class: is anonymous (an inner class, is not a member, is in local scope but is not a 'local class')
Third-Level Class PrivateInnerClass, a member of the anonymous class: is nested, is not local, is not anonymous, is a non-static inner class
You are using the modifier private in (2). Your included JLS text spells out this is illegal:
8.1.1
The access modifier public (§6.6) pertains only to top level classes (§7.6) and to member classes (§8.5), not to local classes (§14.3) or anonymous classes (§15.9.5).
The access modifiers protected and private (§6.6) pertain only to member classes within a directly enclosing class or enum declaration (§8.5).
i.e. you can use none of these modifiers inside (in the scope of) an anonymous class.
Answer to Extra Note 2:
In my understanding, when the Identifier class is an XXX class, what §8.1.1 stated is restricting the modifier of Identifier, not the modifiers in other declarations in ClassBody of Identifier. Otherwise, anonymous classes even cannot have those member fields and methods.
Restriction of modifier before Identifier
This is spelled out in 8.1.1. It clearly applies.
All modifiers can be applied before Identifier of a member class
public can be applied before top-level class Identifier
No modifiers can be applied before Identifier of local/anonymous classes (classes declared in local scope)
Why is this?
Because member classes can be referenced directly by other classes (through a 'member chain' from the top-level class), but local/anonymous classes can never be referenced externally. Local/Anonymous class declarations are hidden in a scope that is itself not accessible to any other part of the java program.
Modifiers are only legal before a class declaration when the declaration is accessible to other classes.
Restriction of modifier within ClassBody
If a class Identifier/Declaration is not accessible to other parts of the java program, of course, the ClassBody is not accessible either.
Hence, whenever a modifier is illegal before the Identifier, a modifier could have no possible semantic meaning within the ClassBody.
The rules for whether a modifier is allowed within ClassBody must always be identical to the rules for whether a modifier is allowed before Identifier.
So 8.1.1. restricts modifiers in both places
:)
You've missed the word 'contain'. PrivateInnerClass is a member of your anonymous class and it is contained within it, so it cannot itself have an access modifier, under rule 14.3.
It can have access modifiers for its own members, but you haven't explored that.
The Eclipse error message wrongly describes it as local.
You've also missed the point that 'private' would add nothing even if it were legal, as the inner class is invisible anyway.
My final answer consists of two thesis:
There is not strong declaration of restrictions for anonymous class members modifiers in the JLS. I.e. there isn't such part of JLS.
But according to JVM specs anonymous classes aren't members of class:
JVM 7 spec: 4.7.6 The InnerClasses Attribute states:
If C is not a member of a class or an interface (that is, if C is a
top-level class or interface (JLS §7.6) or a local class (JLS §14.3)
or an anonymous class (JLS §15.9.5))...
so, according to
8.5 Member Type Declarations
A member class is a class whose declaration is directly enclosed in
another class or interface declaration.
anonymous classes are not member classes.
so, according to 8.1.1. Class Modifiers:
The access modifiers protected and private (§6.6) pertain only to
member classes within a directly enclosing class
this classes aren't member classes, so they can not have mentioned modifiers.
Can a top-level class or interface be declared as static?
Example:
// File A.java
static Class A
{
...
}
No. static only applies to nested classes and tells that instances of the nested class do not need an instance of the surrounding class to be instantiated. As such, it makes no sense as applied to top classes.
Nope, top-level classes cannot be declared static; see JLS Section 8.1.1.
Not all modifiers are applicable to all kinds of class declarations ... The access modifier static pertains only to member classes ...
In java a top level class can't be defined as static.
read this
basically, you can make a static inner class but not top level class(outer one)
I think this post get a better explanation.
http://www.javaworld.com/javaworld/javaqa/1999-08/01-qa-static2.html
hopefully, it helps
All top level classes by default are static.
For those too hooked up about definition of statics and compiler errors.
A class itself is an object with application scope. So it's implicitly static.