My doubt is when I run the following program
public class NonStatic
{
class a
{
static int b;
}
}
The compiler is giving a error that "inner classes cannot have static declarations"
ok,then I made a change instead of "static int b" to "final static int b" its giving
same error but when I wrote "final static int b=10" means with initialization compiler
didn't complain,please can any body explain this what's the concept behind this.
it is so by design, just see the Java Language Specification: 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 members, unless they are compile-time constant fields (§15.28).
final static int b=10
Is interpreted as a constant so compiler can just inline it. Similarly you can have static final constants in interface.
final static int b
Is missing initialization,which is required for final member, so compiler can't quite figure what you want.
Try putting following block right after it out of curiosity:
static {
b=10;
}
Although it probably would not work...
If a field is static, there is only one copy for the entire class, rather than one copy for each instance of the class
A final field is like a constant: once it has been given a value, it cannot be assigned to again. hence when we r using final we have to assign the value to the variable.
have a look at the following link
Here is my take on this issue.
Inner class is defined as a not static member of outer class and hence, it's instance cannot exist without the instance of outer class.
The static fields of a class are accessible without creating an instance of that class.
Now if you add a static field in the inner class, that means you can access that field without create the instance of inner class BUT according to #1 instance of inner cannot exist without an instance of outer class. So this is the conflict and hence the error.
TO CROSSCHECK : Just declare the inner class static and it will correct the error.
Its because a final static variable is a constant meaning it can't change at run time, while a static variable is not a constant and can change during runtime.
So in a class static variables aren't allowed in an inner class but the constants(final) are allowed.
Related
public class Test
{
static int i = 1;
static void m1()
{
}
}
class Test1 extends Test
{
int i = 1; //allowed
void m1() // not allowed; Both are instance level, so why this difference? Both can be accessed with super keyword
{
}
}
Why can't the static method be hidden with the same signature, but the static field is allowed to do this? Both are instance level, so why is only the static field allowed?
m1() in class Test is a static method, while m1() in Test1 is non static. Now imagine if this would have been allowed then which implementation would be picked by runtime when you execute below statement:
new Test1().m1();
Since instance of child class (Test1 in your case) can access also access static method from parent class (from Test). That is why it is not allowed.
For you next question why variable with same name is allowed in Test1: parent class' static variable can not be accessed from child class instance. In other words parent class' static state is hidden from child. That is
Test1.i; // compilation error, can't access parent's static variable
will result in compilation error. And if you try
new Test1().i; // will access Test1's i variable
it will point to the child class' state not parent's. That is why child class can have variable with the same name.
Note: If i in Test was non-static, even in that case Test1 can have variable with name i. In this case i in Test1 will shadow i in Test.
EDIT
From Shahaan Syed's comment:
new Test1().i; why is this allowed is my concerned
To put Shahaan Syed's confusion in another words: Why
in case of variable, child class can have a non-static variable while
parent class has a static variable with the same name,
on the other hand, child class can not have a non-static method when
parent class has a static method with the same name?
As Kevin Esche commented, I also think that Java messed up somewhere by allowing access to static methods of parent class from instance of child class. Though it is not a good practice and compiler generates warning as well.
Here's a quote from (JLS §8.3):
In this respect, hiding of fields differs from hiding of methods
(§8.4.8.3), for there is no distinction drawn between static and
non-static fields in field hiding whereas a distinction is drawn
between static and non-static methods in method hiding.
But I could not find any reasoning behind this in JLS.
I think instead of generating warning there should have been compile time error. That is accessing both static field and static method of parent class from child class instance, should have been compiler error. In this respect things would have been consistent and easy to understand. But again it's just my thought.
Another interesting question on the same line: Why isn't calling a static method by way of an instance an error for the Java compiler?
By Oracle's definition,
Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory.
By this definition, it is safe to deduce that a static variable belongs to the class and shouldn't be accessible for modification by any object of the class.Since all objects share it.
So this line from the same definition is a bit confusing:
Any object can change the value of a class variable...
So I tried this code and it prints 45 (although I get a warning saying "Static member accessed via instance reference"):
public class Main {
static int value = 8;
public static void main(String[] args) {
// write your code here
Main main = new Main();
main.value = 45;
System.out.println(value);
}
}
If this was a Student class, and I had a static variable called numberOfStudents, why should one object of that class be allowed to change the value of this class variable?
It's not really that "one object" can - it's just you're in code which has access to that variable, and unfortunately Java allows you to access static members (both variables and methods) as if they were instance members. This ends up with very misleading code, e.g.
Thread t = new Thread(...);
t.start();
t.sleep(1000);
The last line looks like it's asking the newly-started thread to sleep - but actually it'll make the current thread sleep.
This is basically a flaw in Java. The compiler will silently turn code like this into
Thread.sleep(1000);
or in your case
Main.value = 45;
(I believe that in an older version of Java, it would emit code that checked for nullity with the variable you were accessing the static member "through", but it doesn't even do that any more.)
Many IDEs will allow you to flag code like this with a warning or error. I would encourage you to turn on such a feature. If you see existing code like that, change it to use access the static member directly via the declaring class, so it's clear what's going on.
By this definition, it is safe to deduce that a static variable belongs to the class and shouldn't be accessible for modification by any object of the class.Since all objects share it.
No, static field is accessible for modifications, as long the access modifier allows it.
main.value = 45;
The compiler will read this line at compile-time as:
Main.value = 45;
Being able to create a class with static variables and methods so that those variables and methods are shared by all instances or objects created from the class can be very useful, see When to use static methods.
When sharing a static variable in a class between multiple instances or objects created from the class, the synchronized modifier may be required in order to ensure that if the static variable is being modified by objects in more than one thread, that data integrity is maintained, see What does synchronized mean? and also see How to synchronize a static variable among threads running different instances of a class in java.
The final key word, see How final keyword works is used to determine whether a variable is immutable or not. So if you want to have a class static variable that should be immutable or a constant then you can add the final modifier to the definition. However see Java final keyword for variables which explains that the underlying value for a reference may not be immutable in the sense that functional programming means. See also what is meant by immutable as well as Why final keyword is necessary for immutable class.
You can also use modifiers such as public to determine the visibility of variables and methods in a class, see What does public static void mean in Java.
By using modifiers such as final or private the programmer is able to finely tune the visibility and modifiability of variables in class and objects instantiated from the class.
Litle example how the compiler change the object field access to a class field access.
public class A {
static int foo = 25;
static public void main(String[] arg){
B b = new B();
A a = b;
System.out.println(b.foo);
System.out.println(a.foo);
}
}
class B extends A {
static int foo = 60;
}
The output is:
60
25
It also shows that can be confiusing as it have different behaviour as for object fields.
By this definition, it is safe to deduce that a static variable belongs to the class and shouldn't be accessible for modification by any object of the class.Since all objects share it.
No. By this definition, that static variable belongs to the class and is modifiable by any instance of the class. There is no implication that when some variable is shared that it should not be modifiable. Use final if you want that.
If this was a Student class, and I had a static variable called numberOfStudents, why should one object of that class be allowed to change the value of this class variable?
To increment the value in constructor and decrement it in finalizer, for example.
A static variable has a single instance for the whole class that defines it. When an instance is created, an instance of that static variable IS NOT CREATED. There is only one, and that one is freely modifiable by any function without the need for an instance. (unless it is declared final)
I have a question:
let's say we have this function: (in C++)
int& f() {
static int x = 0;
return x;
} // OK
and
int& h() {
int x=0;
return x;
} // ERROR
Why does h give an error? Is it because of the keyword static? I found static keyword lets my x variable live after my function is terminated. So I still can access at that memory location from the outside (another function or main? right?). Instead int x = 0 is lost after h terminates. Right? I'm not sure I really got it!
And what about Java? I read I cannot declare static variables in methods but only in classes.
Thank you.
In C++, static is one of the most overloaded keywords of the language. The meaning you're using here is this:
A variable which is defined inside a function with the static specifier has static storage duration - it occupies the same space for the entire runtime of the program, and keeps its value between different calls to the function. So you can safely return a reference to it, as the variable is always there to back the reference.
A normal (non-static) function-local variable is destroyed when the function call returns, and so the reference becomes dangling - it doesn't refer to anything valid. Using it results in Undefined Behaviour.
Java simply doesn't have function-scope static variables (it doesn't have that meaning of the keyword static). That's why you can't declare it there.
Both C++ and Java have the "class-scope" meaning of the static keyword. When a member of a class is declared with the static keyword, it means the member is not bound to any instance of the class, but is just a global variable whose identifier lives in the class's scope.
Static keyword is used for almost same purpose in both C++ and Java. There are some differences though.
1) Static Data Members: Like C++, static data members in Java are class members and shared among all objects.
2) Static Member Methods: Like C++, methods declared as static are class members and have following restrictions:
(i) They can only call other static methods.
(ii) They must only access static data.
(iii) They cannot access this or super
Like C++, static data members and static methods can be accessed without creating an object. They can be accessed using class name.
3) Static Block: Unlike C++, Java supports a special block, called static block (also called static clause) which can be used for static initialization of a class. This code inside static block is executed only once (first time you make an object of that class or the first time you access a static member of that class (even if you never make an object of that class)).
4) Static Local Variables: Unlike C++, Java doesn’t support static local variables. If used , Java program fails in compilation.
5) Static class: Classes can also be made static in Java.In java, we can’t make Top level class static. Only nested classes can be static.
Nested static class doesn’t need reference of Outer class, but Non-static nested class or Inner class requires Outer class reference.
Inner class(or non-static nested class) can access both static and
non-static members of Outer class. A static class cannot access
non-static members of the Outer class. It can access only static
members of Outer class.
Ref : www.geeksforgeeks.org
For the Java side you are correct. Static variables in Java must be declared at the class level not inside a method.
If you need to scope the static variables then you probably have some seriously broken architecture but you can do it to a certain extent by using inner classes to store the static variables in.
Static variables in C++ in functions are persistant varibles in the scope of a function. In Java, you can't have static variables in methods. Static variables are variables of the class, not its instances.
Is there any way to access a static member of a nested class from the enclosing class when the nested class shares a name with a static member of the enclosing class? For example:
package a;
class a {
static Object b;
static class b {
static Object foo;
}
static Object needAccessToFoo;
static {
// can I access foo?
}
}
The class b (as opposed to the member b) can be accessed when being used as a Type via a (or [b.]b.a). And foo can be accessed using the instance of the nested class b as so:
static {
[a.][a.]b bar = new b();
needAccessToFoo = bar.foo;
}
However, since b is a nested class and not an inner class, it leaves one to wonder if there is a proper way to statically reference foo without going through an instance of b (the object referred to by bar). Not to mention it's generally accepted as bad practice to access a static member via an object.
This problem is known as Obscuring. The JLS states
A simple name may occur in contexts where it may potentially be
interpreted as the name of a variable, a type, or a package. In these
situations, the rules of §6.5 specify that a variable will be chosen
in preference to a type, and that a type will be chosen in preference
to a package. Thus, it is may sometimes be impossible to refer to a
visible type or package declaration via its simple name. We say that
such a declaration is obscured.
It won't be possible to access foo.
In the context of the static initializer block there are two things with the name b. And because of the rule above, the variable will always be chosen when using that conflicting name. Qualifying the variable with its enclosing type, a.b doesn't change anything because the variable is static and therefore accessible through that reference.
Yes since everything is static and a is in scope of your static block you can do:
static {
Object foo2 = a.foo;
// can I access foo?
}
You will need to rename your outer class though to prevent a name collision. Otherwise how will the compiler know which a you are referring to?
In the following code snippet, presumably it appears that it should issue some compilation error but it doesn't:
class Outer {
public static class Inner {
static String obj = "Inner";
}
static Optional Inner = new Optional();
//The (inner) class name and the object name are same.
}
class Optional {
String obj = "Optional";
}
public class Main {
public static void main(String[] args) {
System.out.println(Outer.Inner.obj);
//Refers to the string inside the optional class
}
}
The class Outer has a static class inside it named Inner. Additionally, it declares an object (static) of the class Optional (static Optional Inner = new Optional();)
This object and the class names (inside the class Outer) are same which is Inner. The program displays Optional. The only expression Outer.Inner.obj within main() is expected to display Inner but it doesn't. The actual output is however Optional which is the case of the Optional class.
One way to display Inner is by changing the object name to something else.
static Optional Inner1 = new Optional();
From the output it displays, it appears that the object name (or a variable) is chosen over a type name (the class Inner) because they have the same name. What exact case is applied here?
Paragraph 6.4.2 of the Java Language Specification has some information about the rules that apply in this case.
A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a visible type or package declaration via its simple name. We say that such a declaration is obscured.
This refers to paragraph 6.5 Determining the Meaning of a Name, which explains the rules in detail.
In your example, Outer.Inner could refer to the type of the nested class named Inner, or the static member variable Inner. The rules say the variable will be chosen over the type.
Actually the class name is Outer$Inner.
Inner classes are essentially a hack introduced in Java 1.1. The JVM doesn't actually have any concept of an inner class, and so the compiler has to bodge it. The compiler generates class B "outside" of class A, but in the same package, and then adds synthetic accessors/constructors to it to allow A to get access to it.
Checkout the following post:
Java inner class visibility puzzle
Think of the inner class has actually have its own .java file.
That will make it clear to you why it chooses the variable over the Inner class.