This question already has answers here:
Are static methods inherited in Java?
(15 answers)
Are static variables inherited
(4 answers)
Closed 4 years ago.
If static members are not inherited in Java then why access modifiers (private, protected…) are applicable to them?
Perhaps, I’m not 100% clear on the term “inherited”:
when they say “statics not inherited” do they mean “not visible” or “can not be redefined/reimplemented” or both?
Would it be correct to say that access modifiers imply only visibility when speaking about static class members, and visibility as well as reimplementation possibility when speaking about regular class members?
Can you please provide examples when making static, say, private makes sense?
Thanks
PS: Now I think that the statement "Static variables in Java are not inherited, they exist only in the class which declares them" spread here and there and around on this forum (for instance: What are the rules dictating the inheritance of static variables in Java?) IS NOT correct as
The Java Language Specification #8.4.8 states:
8.4.8 Inheritance, Overriding, and Hiding
A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:
m is a member of the direct superclass of C.
m is public, protected, or declared with package access in the same package as C.
No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.
If static members are not inherited in Java then why access modifiers
(private, protected…) are applicable to them?
Who said that static members cannot be inhertied, refer following JLS (§Example 8.2-2). example
In Java being "static" simply means that there is no object required to access this field/method.
"private" is just an access modifier which means that following field/method cannot be accessed outside of its, and can only accessed by this class itself or any inner class.
Only thing with "static" methods of a superclass inherited in subclass can be read understood from below excerpt from JLS:
If a class C declares or inherits a static method m, then m is said to
hide any method m', where the signature of m is a subsignature
(§8.4.2) of the signature of m', in the superclasses and
superinterfaces of C that would otherwise be accessible to code in C.
So, basically you cannot override a static method but you can certainly inherit a static method, if it is not hidden by subclass.
Read following JLS section (§8.4.8.2. Hiding (by Class Methods)) about hiding of class methods.
Also, you can read Java's inheritance tutorial from here and below is a screen shot of summary from same page
Member visibility doesn't just apply to child classes. From Oracle, they apply, in reference to a static member, to the rest of the package, or the rest of the "world".
If you create a private static member, you're stating that this is a member exclusive to that specific class. You then work your way up the visibility chain:
private is least visible,
<no modifier> (or package-protected) is second-least visible,
protected is second-most visible, and
public is most visible.
I've not seen anyone really use a protected static member, even though it's valid Java. Convention dictates that this should be a visible constant (in that case it's likely public), or a less-than visible constant for test exposure (which would justify package-protected visibility.
A static member in a class simply means that it will be shared across all the objects of the class. A new variable won't be instantiated for every instance of the class.
Access modifiers control the visibility of variables in Java. The meaning of the access modifiers is the same for static as well as non-static members. It has nothing to do with static members only.
With respect to your question, the use of access modifiers in static variables means the following:
private static count: The static member count is only visible to the class defining it. However, if you inherit the class defining this static variable, your inherited class cannot directly access it. count can be accessed only if super class has a getter defined for it, or if the access modifier is changed to public or protected.
Related
I want to know if static methods and static variables defined in a class are considered members of that class (or if the term 'member' means only instance variables/methods and inner classes)
Which members do classes consist of in Java?
The definition of member in the JLS as defined in §8 is:
The body of a class declares members (fields and methods and nested
classes and interfaces),
So yes static or not, a field or a method is a member of the class. This coincides pretty well with what would commonly be understood as a "member" of something in English. What might be more up to debate is:
The members of a class include both declared and inherited members
Members consists of methods and all variables, be it static or not. However members do not include constructors.
In short, everything (except the constructors) within the class are members, be it inherited from a super class or not and be it static or non-static.
You talk about fields and methods and then quote about static classes, but anyway:
Static members are still members.
Quote from JLS 8.1.6
ClassMemberDeclaration:
FieldDeclaration
MethodDeclaration
ClassDeclaration
InterfaceDeclaration
;
A Field declaration for example is specified here
FieldDeclaration:
{FieldModifier} UnannType VariableDeclaratorList ;
With finally the FieldModifier possibly including static
FieldModifier:
(one of)
Annotation public protected private
static final transient volatile
Why can't constructors be final, static, or abstract in Java?
For instance, can you explain to me why this is not valid?
public class K {
abstract public K() {
// ...
}
}
When you set a method as final it means: "I don't want any class override it." But according to the Java Language Specification:
JLS 8.8 - "Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding."
When you set a method as abstract it means: "This method doesn't have a body and it should be implemented in a child class." But the constructor is called implicitly when the new keyword is used so it can't lack a body.
When you set a method as static it means: "This method belongs to the class, not a particular object." But the constructor is implicitly called to initialize an object, so there is no purpose in having a static constructor.
The question really is why you want constructor to be static or abstract or final.
Constructors aren't inherited so can't be overridden so whats the use
to have final constructor
Constructor is called automatically when an instance of the class is
created, it has access to instance fields of the class. What will be
the use of a static constructor.
Constructor can't be overridden so what will you do with an abstract
constructor.
A Java constructor is implicitly final, the static / non-static aspects of its semantics are implicit1, and it is meaningless for a Java constructor to be abstract.
This means that the final and static modifiers would be redundant, and the abstract keyword would have no meaning at all.
Naturally, the Java designers didn't see in any point in allowing redundant and/or meaningless access modifiers on constructors ... so these are not allowed by the Java grammar.
Aside: It is a shame that they didn't make the same design call for interface methods where the public and abstract modifiers are also redundant, but allowed anyway. Perhaps there is some (ancient) historical reason for this. But either way, it cannot be fixed without rendering (probably) millions of existing Java programs uncompilable.
1 - Actually, constructors have a mixture of static and non-static semantics. You can't "call" a constructor on an instance, and it they are not inherited, or overridable. This is similar to the way static methods work. On the other hand, the body of a constructor can refer to this, and call instance methods ... like an instance method. And then there is constructor chaining, which is unique to constructors. But the real point is that these semantics are fixed, and there is no point allowing a redundant and probably confusing static modifier.
public constructor: Objects can be created anywhere.
default constructor: Objects can be created only in the same package.
protected constructor: Objects can be created by classes outside the package only if it's a subclass.
private constructor: Object can only be created inside the class (e.g., when implementing a singleton).
The static, final and abstract keywords are not meaningful for a constructor because:
static members belong to a class, but the constructor is needed to create an object.
An abstract class is a partially implemented class, which contains abstract methods to be implemented in child class.
final restricts modification: variables become constant, methods can't be overridden, and classes can't be inherited.
Final: Because you can't overwrite/extend a constructor anyway. You can extend a class (to prevent that you make it final) or overwrite a method (to prevent that you make it final), but there is nothing like this for constructors.
Static: If you look at the execution a constructor is not static (it can access instance fields), if you look at the caller side it is (kind of) static (you call it without having an instance. Its hard to imagine a constructor being completely static or not static and without having a semantic separation between those two things it doesn't make sense to distinguish them with a modifier.
Abstract: Abstract makes only sense in the presence of overwriting/extension, so the same argument as for 'final' applies
No Constructors can NEVER be declared as final. Your compiler will always give an error of the type "modifier final not allowed"
Final, when applied to methods, means that the method cannot be overridden in a subclass.
Constructors are NOT ordinary methods. (different rules apply)
Additionally, Constructors are NEVER inherited. So there is NO SENSE in declaring it final.
Constructors are NOT ordinary methods. (different rules apply)
Additionally, Constructors are NEVER inherited. So there is NO SENSE in declaring it final.
No Constructors can NEVER be declared final. YOur compiler will always give an error of the type "modifer final not allowed"
Check the JLS Section 8.8.3 (The JLS & API docs should be some of your primary sources of information).
JLS section 8 mentions this.
Constructors (§8.8) are similar to methods, but cannot be invoked
directly by a method call; they are used to initialize new class
instances. Like methods, they may be overloaded (§8.8.8).
But constructors per say are not regular methods. They can't be compared as such.
why constructor can not be static and final are well defined in above answers.
Abstract: "Abstract" means no implementation . and it can only be implemented via inheritance. So when we extends some class, all of parent class members are inherited in sub-class(child class) except "Constructor". So, lets suppose, you some how manage to declare constructor "Abstract", than how can you give its implementation in sub class, when constructor does not get inherit in child-class?
that's why constructor can't be
abstract .
lets see first
final public K(){
*above the modifier final is restrict 'cause if it final then some situation where in some other class or same class only we will override it so thats not gonna happen here proximately not final
eg:
we want public void(int i,String name){
//this code not allowed
let static,, static itz all about class level but we create the object based constructor by using 'new' keyword so,,,,,, thatsall
abstract itz worst about here not at 'cause not have any abstract method or any declared method
Unfortunately in PHP the compiler does not raise any issue for both abstract and final constructor.
<?php
abstract class AbstractClass
{
public abstract function __construct();
}
class NormalClass
{
public final function __construct() {
echo "Final constructor in a normal class!";
}
}
In PHP static constructor is not allowed and will raise fatal exception.
Here in AbstractClass obviously a constructor either can be declared as abstract plus not implemented or it can be declared as something among (final, public, private, protected) plus a function body.
Some other related facts on PHP:
In PHP having multiple constructor __construct() is not possible.
In PHP a constructor __construct() can be declared as abstract, final, public, private and protected!
This code was tested and stood true for in PHP versions from 5.6 up to 7.4!
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.
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.
In java document, it is said :
Unlike interfaces, abstract classes
can contain fields that are not
static and final, and they can contain
implemented methods.
Is that a correct text? that not part confuses me because interfaces don't have static or final fields, right?
Source : http://download.oracle.com/javase/tutorial/java/IandI/abstract.html
Thanks.
Edit :
public interface GroupedInterface extends Interface1,
Interface2, Interface3 {
// constant declarations
double E = 2.718282; // base of natural logarithms
// method signatures
void doSomething (int i, double x);
int doSomethingElse(String s);
}
An interface can contain constant
declarations in addition to method
declarations. All constant values
defined in an interface are implicitly
public, static, and final. Once again,
these modifiers can be omitted.
Every field declaration in the body of
an interface is implicitly public,
static, and final. It is permitted to
redundantly specify any or all of
these modifiers for such fields.
from section 9.3 of the Java Language Specification (here)
Click on "Defining an Interface" on the link in your question:
An interface can contain constant
declarations in addition to method
declarations. All constant values
defined in an interface are implicitly
public, static, and final. Once again,
these modifiers can be omitted.
That is the correct text.
All fields in an interface are inferred to be public, static and final, whether or not explicitly so declared. Just as all methods are public and abstract, whether or not so declared.
the think is.. all fields inside an interface will be static and final, even if you didnt write the static and final!
The documentation is correct. Interfaces may contain static final fields to be used as constants. Abstract classes may contain instance variables to be inherited by extending classes. Those variables are then available in instances of the extending classes.
The quote is correct. Interfaces can have static final fields, but cannot have any other combination (non-static or non-final).
Fields on an interface are static and final by default, adding the modifiers is not necessary because there's no alternative.
For an abstract class it can make sense to give it mutable state, see java.util.AbstractList. Interfaces are not allowed to have any member that would confer mutable state on a class implementing it.