I have a simple question here.
If I declare a variable inside an object which was made [declared] in the main class, like this:
public static int number;
(
usually I declare it like this :
private int number;
)
can it be used in a different object which was also made [declared] in the main class?
btw I do not care about security atm, I just want to make something work, don't care about protection)
Here's a telling quote from Java Language Specification:
JLS 8.3.1.1 static Fields
If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized.
A field that is not declared static (sometimes called a non-static field) is called an instance variable. Whenever a new instance of a class is created, a new variable associated with that instance is created for every instance variable declared in that class or any of its superclasses.
[Example program follows...]
In short, a static field is a class variable: it belongs to the class, as opposed to the instances of the class. In a way, you can think of a static field as a variable shared by instances of the class, but it's much more consistent to think of static fields as belonging to the class, just like static method also belongs to the class, etc.
Since they belong to the class, they do not require an instance of said class to access (assuming adequate visibility), and in fact it's considered bad programming practice to access static members through an instance instead of a type expression.
Related questions
Java - static methods best practices
Static methods
calling non-static method in static method in Java
non-static variable cannot be referenced from a static context (java)
When NOT to use the static keyword in Java?
Static variables and methods
If the class holding 'number' is called MyClass
you can refer to it as MyClass.number from any method.
Doing so for a variable is not good design though.
There are really two issues here: public vs. private in the context of inner classes, and static variables.
Part 1:
static means that you don't need an instance of the class to access that variable. Suppose you have some code like:
class MyClass {
public static String message = "Hello, World!";
}
You can access the property this way:
System.out.println(MyClass.message);
If you remove the static keyword, you would instead do:
System.out.println(new MyClass().message);
You are accessing the property in the context of an instance, which is a copy of the class created by the new keyword.
Part 2:
If you define two classes in the same java file, one of them must be an inner class. An inner class can have a static keyword, just like a property. If static, it can be used separately. If not-static, it can only be used in the context of a class instance.
Ex:
class MyClass {
public static class InnerClass {
}
}
Then you can do:
new MyClass.InnerClass();
Without the 'static', you would need:
new MyClass().new InnerClass(); //I think
If an inner class is static, it can only access static properties from the outer class. If the inner class is non-static, it can access any property. An inner class doesn't respect the rules of public, protected, or private. So the following is legal:
class MyClass {
private String message;
private class InnerClass {
public InnerClass() {
System.out.println(message);
}
}
}
If the inner class has keyword static, this would not work, since message is not static.
static variables are shared by all instances of a given class. If it's public, it is visible to everything.
non-static variables belong to only one instance.
Since your main method is static, it can only see static variables. But you should avoid working statically - make an instance of a class, and pass the data around as method/constructor parameters, rather than sharing it via static variables.
Related
Why can we access a static variable via an object reference in Java, like the code below?
public class Static {
private static String x = "Static variable";
public String getX() {
return this.x; // Case #1
}
public static void main(String[] args) {
Static member = new Static();
System.out.println(member.x); // Case #2
}
}
Generally, public variables can be accessed by everybody, and private variables can only be accessed from within the current instance of the class. In your example you're allowed to access the x variable from the main method, because that method is within the Static class.
If you're wondering why you're allowed to access it from another instance of Static class than the one you're currently in (which generally isn't allowed for private variables), it's simply because static variables don't exist on a per-instance basis, but on a per class basis. This means that the same static variable of A can be accessed from all instances of A.
If this wasn't the case, nobody would be able to access the private static variable at all, since it doesn't belong to one instance, but them all.
The reason that it is allowed is that the JLS says it is. The specific sections that allows this are JLS 6.5.6.2 (for the member.x cases) and JLS 15.11.1 (in both cases). The latter says:
If the field is static:
If the field is a non-blank final field, then the result is the value of the specified class variable in the class or interface that is the type of the Primary expression.
If the field is not final, or is a blank final and the field access occurs in a class variable initializer (§8.3.2) or static initializer (§8.7), then the result is a variable, namely, the specified class variable in the class that is the type of the Primary expression.
Why are these allowed by the JLS?
Frankly, I don't know. I can't think of any good reasons to allow them.
Either way, using a reference or this to access a static variable is a bad idea because most programmers are likely to be mislead into thinking that you are using an instance field. That is a strong reason to not use this feature of Java.
In your first and second cases you should reference the variable as x or Static.x rather than member.x. (I prefer Static.x.)
It is not best practice to reference a static variable in that way.
However your question was why is it allowed? I would guess the answer is to that a developer can change an instance member (field or variable) to a static member without having to change all the references to that member.
This is especially true in multi-developer environments. Otherwise your code may fail to compile just because your partner changed some instance variables to static variables.
static variables are otherwise called as class variables, because they are available to each object of that class.
As member is an object of the class Static, so you can access all static as wll as non static variables of Static class through member object.
The non-static member is instance member. The static member(class wide) could not access instance members because, there are no way to determine which instance owns any specific non-static members.
The instance object could always refers to static members as it belongs to class which global(shared) to its instances.
This logically makes sense although it is not interesting practice. Static variable is usually for enforcing single declaration of variable during instantiation. Object is a new copy of Class with other name. Even though object is new copy of class it is still with characteristics of the (uninstantiated) Class (first invisible instance). Therefore new object also has that static members pointing to the original copy. Thing to note is: New instance of StackOverflow is also StackOverflow.
I was going through the following code while studying Java local classes :-
class A {
protected int one;
}
class Outer {
static void staticMethod(){
class InnerLocal extends A {
double first = this.one;
double second = super.one;
}
}
}
My doubt is that when we declare the local classes inner to static method or static initializer block then they implicitly work as static member classes as they need no outer class to instantiate them. However I know the difference clearly between a static member class and static local class(i.e. the inner class defined in static block), the problem is that Java does not allows the object references 'this' and 'super' to be used in static context but the code above compiles perfectly.
Can anyone please provide me the reason why Java compiler doesn't complains on using 'this' and 'super' in static context in the above case? Thanks!:)
My doubt is that when we declare the local classes inner to static method or static initializer block then they implicitly work as static member classes as they need no outer class to instantiate them
This is the root cause of your confusion. Just because a method is static does not mean that anything declared within the method is also static. If you declare a variable (say int a) inside a static method, it is said to be a local variable. It would make no sense to say that a is a method local static variable. Similarly, it would make no sense to say that InnerLocal is a method local static class. (There is no such thing as static local variable in Java)
InnerLocal is therefore a regular class that extends from A and inherits the a member variable from A and is able to access it either through this or through super. It would also help to know that final is the only non-access modifier that can be used within a method in Java.
Java does not allows the object references this and super to be used in static context but the code above compiles perfectly.
static as in "static class" is not the same as static as in "static context".
All instance methods and constructors have access to this and super. Since constructors have access to this and super, initializers of instance fields have access to this and super as well. A static inner class has no outer instance, but it has its own instance. That is what this refers to.
In contrast, static methods have no access to this and super, regardless of the class in which these static methods are defined (top-level, static inner, non-static inner, anonymous, etc.)
I am trying to find why the class cant be created as a static? Like:
public static class Qwert{
public static void main(String args[]){
int x = 12;
while(x<12){
x--;
}
System.out.println(" the X value is : "+ x);
}
}
In Java, the static keyword typically flags a method or field as existing not once per instance of a class, but once ever. A class exists once anyway so in effect, all classes are "static" in this way and all objects are instances of classes.
static does have a meaning for inner classes, which is entirely different: Usually an inner class instance can access the members of an outer class instance that it's tied to, but if the inner class is static, it does not have such a reference and can be instantiated without an instance of the outer class. Maybe you saw that someplace, then tried to use it on a top-level class, where it isn't meaningful.
Or maybe you saw it in other languages like C#, whose syntax is an awful lot like Java's.
(One time I couldn't figure out why an outer class instance wasn't being garbage-collected -- it was because I was keeping a reference to one of its inner class instances elsewhere, and the inner class was not static and so had a reference to the outer class instance. So by default, I make inner classes static now.)
To prevent a particular class being instantiated you should add a private Constructor. This stops 'any other' Class from being able to create an object of type Qwert.
for example:
public static class Qwert{
private Qwert() {}
public static void main(String args[]){
int x = 12;
while(x<12){
x--;
}
System.out.println(" the X value is : "+ x);
}
}
We should define members as static which
Should be common to all objects of the class.
Should belong to the class and accessible by class name.
Should not need an object of class to access them.
Now suppose we are defining an outer class as static and suppose we are allowed to do so. Will this serve any purpose or provide any advantage to a developer or it will create ambiguity and complications for both developers and language creators?
Let’s check, defining an outer class as static will serve purposes which we have defined above or not?
Every class is already common to all of its objects and there is no need to make it static to become available to all of its objects.
We need a class name to access its static members because these members are part of class while an outer class is part of package and we can directly access the class by just writing package_name.class_name (similar to class_name.static_field_name), So again there is no need to do which is already there by default.
We do not need any object to access a class if it is visible, we can simply write package_name.class_name to access it. And by definition, a class is a blueprint for its objects and we create a class to create objects from it (exception will always be there e.g. java.lang.Math), again there is no need to define an outer class as static.
From above points, we can say Java creators had not allowed an outer class to be static because there is no need to make it static. Allowing to make the outer class static will only increase complications, ambiguity and duplicity. Read more on Why An Outer Java Class Can’t Be Static
To prevent any class from creating an instance of Qwert, either by inheritance or by using reflection, you make the constructor fail by placing a poison pill:
public class Qwert {
private Qwert() throws IllegalAccessException {
throw new IllegalAccessException("Utility class!");
}
public static class Yuiop {
public Yuiop() throws IllegalAccessException {
// generates a synthetic accessor method to super()
}
}
public static void main(String args[]) {
new Yuiop();
}
}
its because when we use static keyword for a component, that component becomes a class level component and its memory is taken by its class.
In Java, by definition, static applies to the inner components of a class. "X is static" means in Java "X is associated with the class in which it is defined, rather than with any instance of the class".
The word "static" means literally "fixed at one location in memory". Every instance of the class shares a static variable or static member. Hence the use of "class variable" as a synonym for "static variable". Which lets you see at once that you cannot define an outer class as static.
It therefore follows that your class, Qwert, cannot be created as static. Unless it is subsumed as a component of an outer class, effectively making it an inner class.
class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Although it's not possible to access the static field with OuterClass.InnerClass.i, if I want to record something that should be static, e.g. the number of InnerClass objects created, it would be helpful to make that field static. So why does Java prohibit static fields/methods in inner classes?
EDIT: I know how to make the compiler happy with static nested class (or static inner class), but what I want to know is why java forbids static fields/methods inside inner classes (or ordinary inner class) from both the language design and implementation aspects, if someone knows more about it.
what I want to know is why java forbids static fields/methods inside inner classes
Because those inner classes are "instance" inner classes. That is, they are like an instance attribute of the enclosing object.
Since they're "instance" classes, it doesn't make any sense to allow static features, for static is meant to work without an instance in the first place.
It's like you try to create a static/instance attribute at the same time.
Take the following example:
class Employee {
public String name;
}
If you create two instances of employee:
Employee a = new Employee();
a.name = "Oscar";
Employee b = new Employee();
b.name = "jcyang";
It is clear why each one has its own value for the property name, right?
The same happens with the inner class; each inner class instance is independent of the other inner class instance.
So if you attempt to create a counter class attribute, there is no way to share that value across two different instances.
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
When you create the instance a and b in the example above, what would be a correct value for the static variable count? It is not possible to determine it, because the existence of the InnerData class depends completely on each of the enclosing objects.
That's why, when the class is declared as static, it doesn't need anymore a living instance, to live itself. Now that there is no dependency, you may freely declare a static attribute.
I think this sounds reiterative but if you think about the differences between instance vs. class attributes, it will make sense.
The idea behind inner classes is to operate in the context of the enclosing instance. Somehow, allowing static variables and methods contradicts this motivation?
8.1.2 Inner Classes and Enclosing Instances
An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).
InnerClass cannot have static members because it belongs to an instance (of OuterClass). If you declare InnerClass as static to detach it from the instance, your code will compile.
class OuterClass {
static class InnerClass {
static int i = 100; // no compile error
static void f() { } // no compile error
}
}
BTW: You'll still be able to create instances of InnerClass. static in this context allows that to happen without an enclosing instance of OuterClass.
From Java 16 onwards, this is no longer the case. Quoting from JEP 395 (on finalizing records):
Relax the longstanding restriction whereby an inner class cannot declare a member that is explicitly or implicitly static. This will become legal and, in particular, will allow an inner class to declare a member that is a record class.
Indeed, the following code can be compiled with Java 16 (tried with 16.ea.27):
public class NestingClasses {
public class NestedClass {
static final String CONSTANT = new String(
"DOES NOT COMPILE WITH JAVA <16");
static String constant() {
return CONSTANT;
}
}
}
Actually, you can declare static fields if they are constants and are written in compile time.
class OuterClass {
void foo() {
class Inner{
static final int a = 5; // fine
static final String s = "hello"; // fine
static final Object o = new Object(); // compile error, because cannot be written during compilation
}
}
}
class Initialization sequence is a critical reason.
As inner classes are dependent on the instance of enclosing/Outer class, so Outer class need to be initialized before the initialization of the Inner class.
This is JLS says about class Initialization. The point we need is, class T will be initialize if
A static field declared by T is used and the field is not a constant variable.
So if inner class have an static field accessing that will cause initializing the inner class, but that will not ensure that the enclosing class is initialized.
It would violate some basic rules. you can skip to the last section (to two cases) to avoid noob stuff
One thing about static nested class, when some nested class is static it will behave just like a normal class in every way and it is associated with the Outer class.
But the concept of Inner class/ non-static nested class is it will be associated with the instance of outer/enclosing class. Please note associated with instance not the class.
Now associating with instance clearly means that (from the concept of instance variable) it will exist inside a instance and will be different among instances.
Now, when we make something static we expect it will be initialized when the class is being loaded and should be shared among all instances. But for being non-static, even inner classes themselves (you can definitely forget about instance of inner class for now) are not shared with all instance of the outer/enclosing class (at least conceptually), then how can we expect that some variable of inner class will be shared among all the instance of the inner class.
So if Java allow us to use static variable inside not static nested class. there will be two cases.
If it is shared with all the instance of inner class it will violate the concept of context of instance(instance variable). It's a NO then.
If it is not shared with all instance it will violate the the concept of being static. Again NO.
Here is the motivation that I find best suitable for this "limit":
You can implement the behavior of a static field of an inner class as an instance field of the outer object;
So you do not need static fields/methods.
The behaviour I mean is that all inner class instances of some object share a field(or method).
So, suppose you wanted to count all the inner class instances, you would do:
public class Outer{
int nofInner; //this will count the inner class
//instances of this (Outer)object
//(you know, they "belong" to an object)
static int totalNofInner; //this will count all
//inner class instances of all Outer objects
class Inner {
public Inner(){
nofInner++;
totalNofInner++;
}
}
}
In simple words, non-static inner classes are instance variable for outer class, and they are created only when an outer class is created and an outer class object is created at run-time while static variables are created at class loading time.
So non-static inner class is runtime thing that's why static not the part of a non-static inner class.
NOTE: treat inner classes always like a variable for an outer class they may be static or non-static like any other variables.
Because it would cause ambiguity in the meaning of "static".
Inner classes cannot declare static members other than
compile-time constants. There would be an ambiguity about the meaning
of “static.” Does it mean there is only one instance in the virtual
machine? Or only one instance per outer object? The language designers
decided not to tackle this issue.
Taken from "Core Java SE 9 for the Impatient" by Cay S. Horstmann. Pg 90 Chapter 2.6.3
In the Java language designers' own words:
Since nested classes were first introduced to Java, nested class
declarations that are inner have been prohibited from declaring static
members... It simplifies the language's task of resolving and
validating references to in-scope variables, methods, etc.
There was never any particularly grand conceptual or philosophical reason to prohibit this.
Simplifying things for the language was deemed an insufficient reason to continue to maintain this restriction. Along with the introduction of records in Java 16, they made the decision to relax the restriction.
Class Inner will be initialize if a static field declared by Inner is used and the field is not a constant variable.
class Outer{
class Inner{
static Inner obj = new Inner();
}
public static void main(String[] args){
Inner i = Inner.obj; // It woulds violate the basic rule: without existing Outer class Object there is no chance of existing Inner class Object.
}
}
I guess it's for consistency. While there doesn't seem to be any technical limitation for it, you wouldn't be able to access static members of the internal class from the outside, i.e. OuterClass.InnerClass.i because the middle step is not static.
Why can't we have static method in a non-static inner class?
public class Foo {
class Bar {
static void method() {} // Compiler error
}
}
If I make the inner class static it works. Why?
public class Foo {
static class Bar { // now static
static void method() {}
}
}
In Java 16+, both of these are valid.
Because an instance of an inner class is implicitly associated with an instance of its outer class, it cannot define any static methods itself. Since a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference, it's safe to declare static methods in a static nested class.
There's not much point to allowing a static method in a non-static inner class; how would you access it? You cannot access (at least initially) a non-static inner class instance without going through an outer class instance. There is no purely static way to create a non-static inner class.
For an outer class Outer, you can access a static method test() like this:
Outer.test();
For a static inner class Inner, you can access its static method innerTest() like this:
Outer.Inner.innerTest();
However, if Inner is not static, there is now no purely static way to reference the method innertest. Non-static inner classes are tied to a specific instance of their outer class. A function is different from a constant, in that a reference to Outer.Inner.CONSTANT is guaranteed to be unambiguous in a way that a function call Outer.Inner.staticFunction(); is not. Let's say you have Inner.staticFunction() that calls getState(), which is defined in Outer. If you try to invoke that static function, you now have an ambiguous reference to the Inner class. That is, on which instance of the inner class do you invoke the static function? It matters. See, there is no truly static way to reference that static method, due to the implicit reference to the outer object.
Paul Bellora is correct that the language designers could have allowed this. They would then have to carefully disallow any access to the implicit reference to the outer class in static methods of the non-static inner class. At this point, what is the value to this being an inner class if you cannot reference the outer class, except statically? And if static access is fine, then why not declare the whole inner class static? If you simply make the inner class itself static, then you have no implicit reference to the outer class, and you no longer have this ambiguity.
If you actually need static methods on a non-static inner class, then you probably need to rethink your design.
I have a theory, which may or may not be correct.
First, you should know some things about how inner classes are implemented in Java. Suppose you've got this class:
class Outer {
private int foo = 0;
class Inner implements Runnable {
public void run(){ foo++; }
}
public Runnable newFooIncrementer(){ return new Inner(); }
}
When you compile it, the generated bytecode will look as if you wrote something like this:
class Outer {
private int foo = 0;
static class Inner implements Runnable {
private final Outer this$0;
public Inner(Outer outer){
this$0 = outer;
}
public void run(){ this$0.foo++; }
}
public Runnable newFooIncrementer(){ return new Inner(this); }
}
Now, if we did allow static methods in non-static inner classes, you might want to do something like this.
class Outer {
private int foo = 0;
class Inner {
public static void incrFoo(){ foo++; }
}
}
... which looks fairly reasonable, as the Inner class seems to have one incarnation per Outer instance. But as we saw above, the non-static inner classes really are just syntactic sugar for static "inner" classes, so the last example would be approximately equivalent to:
class Outer {
private int foo = 0;
static class Inner {
private final Outer this$0;
public Inner(Outer outer){
this$0 = outer;
}
public static void incrFoo(){ this$0.foo++; }
}
}
... which clearly won't work, since this$0 is non-static. This sort of explains why static methods aren't allowed (although you could make the argument that you could allow static methods as long as they didn't reference the enclosing object), and why you can't have non-final static fields (it would be counter-intuitive if instances of non-static inner classes from different objects shared "static state"). It also explains why final fields are allowed (as long as they don't reference the enclosing object).
The only reason is "not a must", so why bother to support it?
Syntactically,there is no reason to prohibit an inner class from having static members. Although an instance of Inner is associated with an instance of Outer, it's still possible to use Outer.Inner.myStatic to refer a static member of Inner if java decides to do so.
If you need to share something among all the instances of Inner, you can just put them into Outer as static members. This is not worse than you use static members in Inner, where Outer can still access any private member of Inner anyway(does not improve encapsulation).
If you need to share something among all the instances of Inner created by one outer object,it makes more sense to put them into Outer class as ordinary members.
I don't agree the opinion that "a static nested class is pretty much just a top level class". I think its better to really regard a static nested class/inner class as a part of the outer class, because they can access outer class's private members. And members of outer class are "members of inner class" as well. So there is no need to support static member in inner class. An ordinary/static member in outer class will suffice.
From: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
Oracle's explanation is superficial and handwavy. Since there's no technical or syntactic reason to preempt static members within an inner class (it's allowed in other languages such as C#) the Java designers' motivation was likely conceptual taste and/or a matter of technical convenience.
Here's my speculation:
Unlike top-level classes, inner classes are instance-dependent: an inner-class instance is associated with an instance of every one of its outer classes and has direct access to their members. This is the chief motivation for having them in Java. Expressed another way: an inner class is meant for instantiation in the context of an outer class instance. Without an outer class instance, an inner class ought not be any more usable than the other instance members of the outer class. Let's refer to this as the instance-dependent spirit of inner classes.
The very nature of static members (which are NOT object-oriented) clashes with the instance-dependent spirit of inner classes (which IS object-oriented) because you can reference/call a static member of an inner class without an outer class instance by using the qualified inner class name.
Static variables in particular may offend in yet another way: two instances of an inner class that are associated with different instances of the outer class would share static variables. Since variables are a component of state, the two inner class instances would, in effect, share state independently of the outer class instances they're associated with. It’s not that it’s unacceptable that static variables work this way (we accept them in Java as a sensible compromise to OOP purity), but there’s arguably a deeper offense to be had by allowing them in inner classes whose instances are already coupled with outer class instances by design. Forbidding static members within inner classes in favor of the instance-dependent spirit reaps the added bonus of preempting this deeper OOP offense.
On the other hand, no such offense is entailed by static constants, which do not meaningfully constitute state and so these are allowable. Why not forbid static constants for maximum consistency with the instance-dependent spirit? Perhaps because constants need not take up more memory than necessary (if they're forced to be non-static then they’re copied into every inner class instance which is potentially wasteful). Otherwise I can’t imagine the reason for the exception.
It may not be rock-solid reasoning but IMO it makes the most sense of Oracle's cursory remark on the matter.
Short answer: The mental model most programmers have of how scope works is not the model used by javac. Matching the more intuitive model would have required a big change to how javac works.
The main reason that static members in inner classes are desirable is for code cleanliness - a static member used only by an inner class ought to live inside it, rather than having to be placed in the outer class. Consider:
class Outer {
int outID;
class Inner {
static int nextID;
int id = nextID++;
String getID() {
return outID + ":" + id;
}
}
}
Consider what is going on in getID() when I use the unqualified identifier "outID". The scope in which this identifier appears looks something like:
Outer -> Inner -> getID()
Here, again because this is just how javac works, the "Outer" level of the scope includes both static and instance members of Outer. This is confusing because we are usually told to think of the static part of a class as another level of the scope:
Outer static -> Outer instance -> instanceMethod()
\----> staticMethod()
In this way of thinking about it, of course staticMethod() can only see static members of Outer. But if that were how javac works, then referencing an instance variable in a static method would result in a "name cannot be resolved" error. What really happens is that the name is found in scope, but then an extra level of check kicks in and figures out that the name was declared in an instance context and is being referenced from a static context.
OK, how does this relate to inner classes? Naively, we think there is no reason inner classes can't have a static scope, because we are picturing the scope working like this:
Outer static -> Outer instance -> Inner instance -> getID()
\------ Inner static ------^
In other words, static declarations in the inner class and instance declarations in the outer class are both in scope within the instance context of the inner class, but neither of these is actually nested in the other; both are instead nested in the static scope of Outer.
That's just not how javac works - there is a single level of scope for both static and instance members, and scope always strictly nests. Even inheritance is implemented by copying declarations into the subclass rather than branching and searching the superclass scope.
To support static members of inner classes javac would have to either split static and instance scopes and support branching and rejoining scope hierarchies, or it would have to extend its simple boolean "static context" idea to change to track the type of context at all levels of nested class in the current scope.
Why can't we have static method in a non-static inner class ?
Note: A non-static nested class is known as inner class so you do not have non-static inner class as such.
An inner class instance has no existence without a corresponding instance of outer class. An inner class cannot declare static members other than compile time constants. If it were allowed then there would have been ambiguity about meaning of static. In that case there would have been certain confusions:
Does it mean there is only one instance in VM?
Or only one instance per outer object?
That is why the designers probably took the decision of not handling this issue at all.
If I make the inner class static it works. Why ?
Again you cannot make an inner class static rather you can declare a static class as nested. In that case this nested class is actually part of outer class and can have static members without any issue.
This topic has garnered attention from many, still I will try to explain in the most simplest of terms.
Firstly, with reference to http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1, a class or interface is initialized immediately before the first occurence/invocation of any member which is preceeded by the static keyword.
So, if we put up with a static member within an inner class, it will lead to the initialization of the inner class, not necessarily the outer/enclosing class. So, we hamper the class initialization sequence.
Also consider the fact that a non-static inner class is associated with the instance of an enclosing/outer class. So, associating with an instance will mean, that the inner class will exist inside an Outer class instance and will be different amongst instances.
Simplifying the point, in order to access the static member we need an instance of an Outer class, from which we will again need to create an instance of non-static inner class. Static members are not supposed to be bound to instances and therefore you receive a compilation error.
The work to add records to JDK16 also mentions that static methods and fields can now be used with inner classes, even permitting main() to launch the class.
For example this compiles and runs in JDK16, and can select either main() to be run as java Outer or java Outer$Inner:
public class Outer {
public static void main(String[] args) {
System.out.println("Outer class main xxx="+Inner.xxx+" nnn="+(++Inner.nnn)+" iii="+(--iii));
aaa();
Inner.zzz();
}
public static void aaa() {
System.out.println("aaa() nnn="+(++Inner.nnn)+" iii="+(--iii));
}
public static int iii = 100;
class Inner {
public static final String xxx= "yyy";
public static int nnn = 0;
public static void zzz() {
System.out.println("zzz() "+" nnn="+(++nnn)+" iii="+(--iii));
}
public static void main(String[] args) {
System.out.println("Inner class main xxx="+xxx+" nnn="+(++nnn)+" iii="+(--iii));
zzz();
aaa();
}
}
}
An inner class is something completely different from a static nested class although both are similar in syntax. Static nested classes are only a means for grouping whereas inner classes have a strong association - and access to all values of - their outer class. You should be sure why you want to use an inner class and then it should come pretty natural which one you have to use. If you need to declare a static method it's probably a static nested class you want anyway.
First of all why someone want to define the static member in a non-static inner class? answer is, so that the outer class member can use those static member with the inner class name only, Right?
But for this case we can directly define the member in outer class. which will be associated with all object of inner class, within the outer class instance.
like below code,
public class Outer {
class Inner {
public static void method() {
}
}
}
can be written like this
public class Outer {
void method() {
}
class Inner {
}
}
So in my opinion not to complicate the code java designer is not allowing this functionality or we may see this functionality in future releases with some more features.
suppose there are two instances of outer class & they both have instantiated inner class.Now if inner class has one static member then it will keep only one copy of that member in heap area.In this case both objects of outer class will refer to this single copy & they can alter it together.This can cause "Dirty read" situation hence to prevent this Java has applied this restriction.Another strong point to support this argument is that java allows final static members here, those whose values can't be changed from either of outer class object.
Please do let me if i am wrong.
Try to treat the class as a normal field, then you will understand.
//something must be static. Suppose something is an inner class, then it has static keyword which means it's a static class
Outer.something
You are allowed static methods on static nested classes. For example
public class Outer {
public static class Inner {
public static void method() {
}
}
}
It is useless to have inner class members as static because you won't be able to access them in the first place.
Think about this, to access a static member you use className.memberName ,, in our case , it should be something like outerclassName.innerclassName.memberName,,, now do you see why innerclass must be static....