Why enum constructor can't access static field [duplicate] - java

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can’t enum’s constructor access static fields?
enum Test {
e1,e2;
int i=0;
static int j=5;
Test(){
System.out.println(i+" "+j);
}
}
In the above code the constructor can access the instance variable but not the static variable J.
I have read the answer relate to other author all are saying the e1 and e2 initialized before the initialization of J( static field), But according java spec all the static field
initialized when ever the class loaded to memory, that is before running of the constructor.
So before running of Test() constructor the static variable j must be initialized. I'm not able understand the restriction, can any body make me understand.I have already read the answer of the questions Why can't enum's constructor access static fields? But I am not happy with answer like :-The constructor is called before the static fields have all been initialized.
Suppose if take another example with a simple class like enum
class Test{
public static final Test t=new Test();
static int a=5;
Test(){
System.out.println(a);
}
public static void main(String[] args) {
}
}
Here according to there argument the constructor will run before the initialization of static field and it's running also as it's print 0(As JVM did the initilization). But no compilation error or no run time problem. Then why the same thing not happen with enum.

If you imagine how your enum would actually look as a class, it makes sense:
public class Test {
// Imagine you cannot move these two statements:
public static final Test e1 = new Test();
public static final Test e2 = new Test();
int i=0;
static int j=5;
private Test(){
System.out.println(i+ " " + j);
}
static int getJ() {
return j;
}
public static void main(String[] args) {
System.out.println(Test.getJ());
}
}
This prints:
0 0
0 0
5
If you can share a concrete example (rather than a theoretical one), we could suggest how to redesign the code to achieve the desired result, despite the static field limitations.

Problem is, that instances of enum are created during inicialization of static fields. And they created before initialization of your static fields.
They must be in static array values and statically accessible, so it makes sense. And as stated in anser to "Why can't enum's constructor access static fields?", its unfortunate that this happens before all user defined static field inicialization.
But if it was swapped, you could not acces enum instances in static initialization, so it would need allowing static block both before and after creation of enum values.
I don't know whether problem is because inicialization of enum values is concern of Enum class (and handled specialy by JVM (this logic is not in Enum class itself), or because you cannot put static fields before enum values.
WHY it is that way can answer only few people (eg. Josh Bloch and Neal Gafter who are stated as authors of Enum in javadoc, and maybe some unknown others)

Related

Can static assignments be re-ordered by the compiler in Java 8+? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java static class initialization
Why is the string variable updated in the initialization block and not the integer(even though the block is written first)
class NewClass
{
static
{
System.out.println(NewClass.string+" "+NewClass.integer);
}
final static String string="static";
final static Integer integer=1;
public static void main(String [] args)//throws Exception
{
}
}
My output is
static null
P.S:Also noticed that string variable initialization happens before the block only when i insert the final modifier. why is that?why not for integer as well?I have declared it as final static too
From section 12.4.2 of the JLS, snipped appropriately:
The procedure for initializing C is then as follows:
Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
So for non-compile-time-constants, it's not a case of "all variables" and then "all static initializers" or vice versa - it's all of them together, in textual order. So if you had:
static int x = method("x");
static {
System.out.println("init 1");
}
static int y = method("y");
static {
System.out.println("init 2");
}
static int method(String name) {
System.out.println(name);
return 0;
}
Then the output would be:
x
init 1
y
init 2
Even making x or y final wouldn't affect this here, as they still wouldn't be compile-time constants.
P.S:Also noticed that string variable initialization happens before the block only when i insert the final modifier.
At that point, it's a compile-time constant, and any uses of it basically inlined. Additionally, the variable value is assigned before the rest of the initializers, as above.
Section 15.28 of the JLS defines compile-time constants - it includes all primitive values and String, but not the wrapper types such as Integer.
Here is a short and straight forward answer to you question....
static Variable :
static Variables are executed when the JVM loads the Class, and the Class gets loaded when either its been instantiated or its static method is being called.
static Block or static Initializer Block :
static static Initializer Block gets Initialized before the Class gets instantiated or before its static method is called, and Even before its static variable is used.
///////// Edited Part /////////
class NewClass {
final static String string = "static";
final static Integer integer = 1;
static {
System.out.println(NewClas.string + " " + NewClas.integer);
}
public static void main(String [] args) { // throws Exception
new NewClas();
}
}
The above will print static 1.
The reason is that the JVM will do the optimization process known as Constant folding, doing an pre-calculation of the constant variables.
Moreover in your case the result was static null cause Constant folding is applied to Primitive type and not Wrapper Object, in your case its Integer...
They are initialized in the given order (fields and static blocks), that's why printed value is null, nothing was assigned to static fields that are defined after the static block.

Can i initialize static variable after the initialization?

What is the problem with below code?
class test {
static int a;
a=10;
}
If I'm writing like this (as above), I'm getting a compile time error.
class test {
static int a=10;
a=4;
}
For the second one, I'm not getting any error.
Neither of your examples should compile.
a=10;
is a statement, which is not valid directly inside a class declaration. You can only put the following directly inside a class:
Member declarations (member/static variable declarations (like static int a;), methods, nested classes and interfaces);
Static and instance initializers;
Constructors.
You need to put a statement inside a block, for example a static initializer:
static int a;
static {
a = 10;
}
which is equivalent to:
static int a = 10;
You need to use a static block of statement to do an assignment on an other line (outside a method)
class test {
static int a;
static { a=10; }
}
a=4; must be done in a valid scope
either a method or a constructor...
this line is valid instead
static int a=10;
because java allows youto declare and initialize in one statement!
If you want to initialize a after defining it as a null int, you can only do that in a function, because it is static.
must be initialized inside static block or init block or in constructor.
you can only initialized your member variable after declaration inside a function or block because it is static you should use static block
What you are currently doing is declaring a variable in a class decleration, which is not valid. Looking at this neither of your examples should give you any good result.
In a class declaration you can however initialize a variable:
static int a;
Then if you want to work with it you would have to create a method first (if you are not aware of this I would strongly advise to watch some youtube tutorials or read books about this topic) :
public void foo(int a){
a = 6; //Here you can play with your variables and change them
}
In class declararions you can: declarations methods, initializers and constructors. (there is a bit more you can do, however I would have a look at these points before diving in too deep).
Furthermore it seems that you are not aware what a static variable or a static method does, I think the following posts will help you with that:
difference between 'static int' and 'int' in java
What are static method and variables?
I hope I could help and have fun learning Java
Because for static memory allocated at the time of class loading
so we need do like this
class test {static int a =10;
public static void main(String args[]) { a=12 output(test.a (or) a);}}
A Java class body is should contain declarations and declaration with an initializer, not the standalone statements. Let's unwrap your requirement of initializing a static variable.
Static variables should not be initialized inside methods as these variables belong to the class. But they can be initiated inside the constructor.
public class Example {
static String name;
static int age;
Example() {
name = "James";
age = 34;
}
public static void main(String args[]) {
new Example();
System.out.println(Example.name);
System.out.println(Example.age);
}
}
Now the output will be :
James
34
If new Example(); is not called then the output will be :
null
0
This is because the static variables are initialized with an object creation and for each Example object name and age will be overwritten with the same value. But at least one object needs to be created for name and age to be initialized.
But if you declare a static and final instance variable, we cannot initialize that in the constructor, it is mandatory to initialize static and final variables at the class level. We can initialize while declaring the variable or using a static initialization block. This runs before the main() method in Java. Hence when the main() method is loaded this static variable will be initialized and the compiler will not throw any errors.
static final int name = "STRING";
static final int age;
static {
age = 10;
}
Putting all these things together,
A static variable can be initialized,
When declaring.
Inside a constructor.
Inside a static block.
A static final variable can be initialized,
When declaring.
Inside a static block.
A final variable can be initialized,
When declaring.
Inside a constructor (If you have more than one constructor in your class then it must be initialized in all of them).

Enum - static initialization order [duplicate]

This question already has answers here:
Why can't enum's constructor access static fields?
(5 answers)
Closed 9 years ago.
Accessing static variables in constructor of enum class is forbidden in java. Why in enumerations the order of static initialization is not swapped?
Example of correct code:
enum Test
{
TEST1, TEST2;
static int x;
}
Why do developers of java did not created such code as correct:
enum Test
{
static int x;
TEST1, TEST2;
}
Then static variables could be used in constructor. Now it is forbidden.
Does it have any reason or it is just their design?
Well, it's to ensure safe instance initialization - the enum instances are very similar to static final instances of the enum class, and the language has defined that they be initialized first.
But if you know a trick or two you can effectively use static variables in an enum constructor:
enum Test {
TEST1, TEST2;
static class Holder {
static int x;
}
Test() {
Holder.x++; // no compiler error
}
}
For more info see Initialization-on-demand holder idiom
From JLS (§8.9):
An enum declaration specifies a new enum type
EnumDeclaration:
ClassModifiersopt enum Identifier Interfacesopt EnumBody
EnumBody:
{ EnumConstants-opt ,opt EnumBodyDeclarations-opt }
As you can see, the body should be defined with enum-constants declared first and other body declarations may follow - not the other way around!
Further, you don't have to use lazy initialization like bohemian suggested you can do it in a simpler manner. According to JLS you can't do:
enum Test {
TEST1, TEST2;
static int x;
Test(){
x = 1; // <-- compilation error!
}
}
but you can use static initializer block:
enum Test {
TEST1, TEST2;
static int x;
static{
x = 1; // works!
}
}
The reason that you CAN use the latter is that static declarations are executed in the same order they were declared - assigning x=1 will occur only after x was declared, unlike using a constructor. If you want to verify it - you can add System.out.println() calls to the constructor and static block - you'll see that the constructor is being executed first.

Why should a static method in java accept only final or non final variables within its method, but not static?

Why should a static method in java accept only final or non final variables within its method, but not static?
For example I have the following method:
public static void myfunc(int somethig)
{
int a=10;
final int b=20;
static int c=30; //gives Error why?
}
The question is: why not?
Consider this: what would a static local variable mean?
I suggest that the only sensible meaning would be that this:
public class Foo {
static int bar = 21;
public void foo() {
static int bar = 42; // static local
return bar;
}
}
is equivalent to this:
public class Foo {
static int bar = 21;
private static foo$bar = 42; // equivalent to static local
public void foo() {
return bar;
}
}
In other words, (hypothetical) static locals would be equivalent to regular static attributes with slightly different visibility rules.
The Java language designers probably considered this, and decided that static locals added so little of real value that they were not worth including in the language. (Certainly, that's the way I would have voted.)
In Java (in Object Oriented Programming in general), objects carry state. Methods should share state through objects attributes, not through static local variables.
You can't have static local variable. It doesn't really make sense.
However you can have a static field in your class.
Resources :
JLS - Local Variable Declaration Statements
You can not have a static variable. There is no such thing. You can have a class variable as static instead.
Since every function in java has to be inside a class, you can get the same effect by declaring fields in your class. It's the simplest way, and java language designers are very conservative. They'd never add a feature like that, when there's a more obvious and less complex way to do the same thing.
EDIT: I guess philosophically functions aren't first class in java. They're not supposed to store data. Classes are, and they do.

Static members in Java [duplicate]

This question already has answers here:
Are static methods inherited in Java?
(15 answers)
Closed 4 years ago.
I've read Statics in Java are not inherited. I've a small program below which compiles and produces 2 2 as output when run. From the program it looks like k (a static variable) is being inherited !! What am I doing wrong?
class Super
{
int i =1;
static int k = 2;
public static void print()
{
System.out.println(k);
}
}
class Sub extends Super
{
public void show()
{
// I was expecting compile error here. But it works !!
System.out.println(" k : " + k);
}
public static void main(String []args)
{
Sub m =new Sub();
m.show();
print();
}
}
The scope in which names are looked up in includes the super class.
The name print is not found in Sub so is resolved in the Super.
When the compiler generates bytecode, the call will be made to Super.print, rather than a call on a method in Sub.
Similarly the k is visible in the sub-class without qualifying it.
There is no polymorphism here, only inheritance of the contents of a name space. Static methods and all fields do not have polymorphic dispatch in Java, so can only be hidden by sub-classes, not overridden. The post you link to in your comments is using 'inheritance' in a somewhat unconventional way, mixing it up with polymorphism. You can have polymorphism without inheritance and inheritance without polymorphism.
Sub extends Super so it can see all the public/protected/package (static) members of Super.
I guess this is what you described as "Statics in Java are not inherited"
change
static int k = 2;
to
private static int k = 2;
and your Sub program won't see 'k' anymore and won't compile;
also try to create a new 'static int k=3;' in Sub, and see what happens.
It's pretty much the same as accessing Math.PI or any other global constant (which also have public and final modifiers).
In your case you have default (package) scope.
It's independed of inheritance only the scope restricts whether it is visible.
I think you might be wrong about static variables not being inherited. I suppose some properties of it are not inherited. For instance a static var normally means that all instances of the class have access to the same place in memory.
When you inherit, the derived class does not refer to the same memory as the base class.
Static member can be static data member and static method which can be accessed without using the object. It is used by nested class

Categories