I understood that I can't call a non static variable from a static context; and when I try to assign the non static variable B to the static A in between the Solution class, it doesn't work. So far good, but why does it work in the main via creating an object before?
So, why doesn't this work???
While this does work, isn't this still a static context???
Please help, this is messing up my system! Question about the static variable
In der Diskussion
Kommentare (26)
- Beliebt
- Neu
- Alt
Du musst angemeldet sein, um einen Kommentar schreiben zu können
Guadalupe Gagnon
12 April 2023, 13:33
I think you mis-understand. Fields that are not static, such as B and C, are only created when objects of the class type they are contained in (in this case the Solution class) are created. Static fields, on the other hand, are created when a class is pre-loaded into memory, which occurs directly before any static method belonging to that class is called or directly before the first object is created. The static keyword tells the compiler that the field or method is object independent and therefore exists and can be used without creating any objects unlike class fields.
Your first example does not work because you can not set the static variable A to the class variable B because you are using B in a static context (without an appropriate object). Therefore while A exists at that point, B does not. It would work fine if you created an object and used that object to access the B variable. See this legitimate, although a little mind bending, example:
0
Guadalupe Gagnon
12 April 2023, 13:57
As I said, that example is a little mind bending. When main is called the static variables are the first to be set up, in order.
1) So first line 2 is set up giving values to test.B and test test.C.
2) next line 4 is run and it outputs that test.A is 0.
3) next line 6 is run and A is set to test.B (5) + 2. So at this point A is set to 7
4) next line 11 is run and A is output again. This time it outputs 7
5) nest, line 12, test.C is output. Its value is 5 because when line 2 is run the static variable A had a default value of 0 when test.C is created.
6) finally, line 13, a new Solution object is created and its C is output, the value is 12
+1
Andreas Blank
18 April 2023, 17:07
Thank you, mate, for your nice answer. I still need to take it all in. But please allow me two additional questions:
1) Why does my second example work? s1.B is a nonstatic variable and we assign it to the static variable A. In my understanding the rule was a static variable can be called from a nonstatic environment but, vice versa, a nonstatic variable can not be called from a static environment... right?
2) Because as I understood, the following does not work because "s1" is not static, right. when i modify it s1 with the keyword static, all is good
Solution s1 = new Solution();
public static int A = s1.B;
public int B = 2;
public int C = A * B;
But in between the main method, the following, same approach works... why?
s1 is not static, but I can assign it to A.
public static void main(String[] args) {
Solution s1 = new Solution();
A = s1.B;
+1
Guadalupe Gagnon
18 April 2023, 17:50
1) non static variables need an object created to exist. The object is s1, and B exists in that object and can be used.
2) Right. s1 in your first example:
s1 is not static and therefore can not be used until an object is created. This is because it is part of the class definition and is a field that only exists as part of an object. This is the same as B not existing until an object is created. In your second example:
The main method, which is where executable code starts, an object is created and in turn the object fields (the non static ones) are created for that object only and can be used. Each new object created will have duplicate fields with unique values. This is important to remember because class fields (the static ones) belong to the class and only have 1 value. You can access and modify the static fields with an object variable but that field will still only have one value even if you access it from a different object.
This is all very logical, however it is hard to wrap your mind around when you are first learning programming. I will post an example of this that shows the difference between the class and object (static and non-static) fields. +1
Guadalupe Gagnon
18 April 2023, 18:04
+1
Andreas Blank
19 April 2023, 12:48
I roughly understood the concept of static and non static variables.
Solution s1 = new Solution();
public static int A = s1.B;
public int B = 2;
public int C = A * B;
But under this example I also created an object which then should allow to access the instance variables. So, my question still refers to why it works under example two where the object is created in the main method while it doesn't work when I create the object to access the variable in the class. Can you please explain this to me?
Because, in the example you brought up the object was also created in the class
public class Solution {
static Solution test = new Solution();
The only difference is that you declared it as a static variable. Does it work because of this?
+2
Guadalupe Gagnon
19 April 2023, 13:52
Where you are putting the variable is in the class definition, which is anything inside the class block of code not within another block of code, such as a method. Methods are actually part of the class definition. A very simple way to tell what is part of the class definition is to visually see what is indented 1 time inside the class. Of course this is only helpful when things are properly indented. In the compiler ignores all white space so you don't have to follow the rules for proper indentation. Here is an example of a class, its "definition", and proper indentation:
In this code you just have an example class simply called Example. The "definition" of this class is everything that is indented 1 time. This includes:
- a String field named A
- an int field named B
- a void method doSomething()
- a method getA() that returns a String
In this example I don't use any static fields or methods, which means to use this class in any capacity you need to create an object. None of the fields or methods exist otherwise. People use the analogy of a blueprint to associate with classes. A blueprint describes how to build something, like a house or a car. A class only describes how to build something. Until an object is created a class is only a blueprint; such as until a house is built a blueprint is just a piece of paper. In your example the variable s1, when it is not static, does not exist until an object is created. When you create an object s1 will then be created and set to equal a new Solution(). +1
Guadalupe Gagnon
19 April 2023, 14:01
Where you are getting confused is where static and non-static variables are interacting. When you have a class you can use the fields to set the values of other fields, but you have to remember that the non-static parts don't exist until an object while the static parts are pre-loaded into memory. This means that static fields exist BEFORE any non-static fields. Therefore it is illegal to use non-static fields to set values of static fields. Also, because static fields already exist when an object is created, you can use static fields to set values of non-static fields. You can also use non-static fields to set values of other non-static fields because they are created at the same time (at the point an object is created).
Going back to your example:
in this code line 2 is created 1st because it is static, so at the point of its creation the variable s1 does not exist. You'll get a red squiggly line there in IntelliJ informing you of the error and the code will not compile. As a beginner it is easier to list the static variables first to help avoid this mistake, but once you understand the rules it makes no difference. +1
Guadalupe Gagnon
19 April 2023, 14:24
One last interesting thing. Putting a non-static field of the same class that creates an object will result in an infinitely repeating sequence of object creation up until the computer runs out of memory and the program crashes. This is because the field is only created when an object is created:
The field s1 is created any time a new Solution object is created. The main method is called to start the program and line 5 creates the first Solution object. For that object to fully be created line 2 needs to execute, which creates a new Solution object. For that line to be created, line 2 (for the second object being created) would create a new Solution object. That would also create a new Solution object. That would also create a new Solution object. etc etc...
If you ran this code it will crash with a stack overflow exception. +1
Andreas Blank
19 April 2023, 14:26
So, first let me thank you for your support because you bring up didactically good stuff, and actually I am a bit sorry that I gotta ask one more question; but I just want to make sure. So, are you saying that the constructing of objects can only be triggered from the main method and this is why I don't have an created object?
If so, I think your code confused me:
public class Solution {
static Solution test = new Solution();
static {
System.out.println("Printing A in static block: " + test.A);
}
static int A = test.B + 2;
int B = 5;
int C = A + B;
public static void main(String[] args) {
System.out.println("Printing A in main method: " + test.A);
System.out.println("test.C: " + test.C);
System.out.println("new Solution().C: " + new Solution().C);
}
}
Because here you also created an object in the class, outside the main method, and call the variable. Why does it in your case work?
Because the reference variable "test" you create is static but in the way I understood things, you can't call the constructor outside the main (unless it gets called through some other method triggered in the main). Does it work because you have "test" declared as a static variable?
Thanks in regards
+1
Andreas Blank
19 April 2023, 14:34
Regarding your explanation:
Why is your code working then?
public class Solution {
static Solution test = new Solution();
static {
System.out.println("Printing A in static block: " + test.A);
}
static int A = test.B + 2;
int B = 5;
int C = A + B;
public static void main(String[] args) {
System.out.println("Printing A in main method: " + test.A);
System.out.println("test.C: " + test.C);
System.out.println("new Solution().C: " + new Solution().C);
}
}
Because only in line 15 you create a new Solution object which can trigger the "test" object to be there. But you assign it to static int A variable much earlier... And the compiler works?
So, why does the assignment work? And why is it no case where the memory runs out? Because actually always you create a new object, the class again creates a new object, the class creates a new object and so on... I guess that is because it is static and then avoids the loop... But could you say some words to this case and also why the assignment of test.B + 2 is legit, please?
+1
Guadalupe Gagnon
19 April 2023, 14:46
"I am a bit sorry that I gotta ask one more question"
Don't be. I enjoy programming and I enjoy helping other people enjoy it as well.
I have been typing a lot at the same time you have been typing and i may have already answered this in your other post.
The code for fields is executed only at the point of creation. For static fields this occurs when the class code is loaded into memory, for non-static fields this occurs when an object is created.
Code in methods is executed when a method is called. Static methods, such as main, do not require any objects, while non-static methods require an object.
In that code the first thing that is executed is, in order, are the static fields. You haven't seen static blocks yet, but they execute at the same time the static fields (in order with the fields too). So first the variable test is created. Next, in the static block, I output test.A. I have to do it this way because simply outputting A will result in an error because the static block is before A. This is a bit advanced so won't explain that little hiccup at this point. I output the value of A at this point to show you that it has not been set to test.B + 2 and instead outputs 0 (which is the default value). Next A is finally set to its value. After the fields and static blocks are executed the main method is executed. Even if you moved the main method in the code, the fields and static blocks execute first. Even if you put main right under the line public class Solution, it wouldn't change the order.
Then in main I output 3 lines, first the value of A. You can change that to simply A instead of test.A and you will get the same result. I used test.A to show you that the value did indeed change from 0. Then I output test.C, which is going to be 5 because when test was created A was only 0 (from the first output. Finally I created a new object and output that objects C, which output 12 because A had a value of 7 when that object was created.
+2
Andreas Blank
19 April 2023, 15:05
Ok, there is a lot to learn from your answer.
1) So, is it that in your static variable "test" an Solution object can be created through calling the class' constructor without being called from the main method? Because in my understand before your teaching, I would've that test would be declared but not assigned to null as a default value until a new object is created in the main...
2) In your last print, where you call new Solution().C, would it have been the same result calling test.C?
+1
Guadalupe Gagnon
19 April 2023, 15:30
I am going to get a little more advanced in this post:
When a class is used a specific set of steps occur.
1) the entire class code is loaded into memory
2) next the static fields are created and set to default values (0 for primitives and null for objects)
3) next the static fields and static blocks are executed in order from the top of the code to the bottom of the code. This is where they are initialized
When an object is created the steps 1 and 2 are repeated but now for the non-static fields and blocks.
1) The non-static fields are created and set to default values (0 for primitives and null for objects)
2) next the non-static fields and static blocks are executed in order from the top of the code to the bottom of the code. This is where they are initialized
So, an object can actually be created during step 3 of the static creations which will kick in the steps of the object creation. This occurs on the static line that the object is created on and is finished before moving onto the next static line. This was demonstrated in the example I shared. here is another example just showing these steps a little more simply:
0
Guadalupe Gagnon
19 April 2023, 15:53
run this code and see the output. I'll explain below:
In this code, it is first "used" when the main method is called, which is the entry point of every Java application. So step says that the entire class code is loaded into memory. This helps the compiler know what to do when a static variable or a method is accessed BEFORE it is defined in the code. Next the static variables are created and set to default values. That would be step 1 and 2.
Next step 3 starts and the first to occur is the static block on lines 7-9 output the value of the static variable A. So at this point, if steps 1 and 2 had not occurred then A would not exist and the code wouldn't compile, but the code compiles and the first output occurs that shows the value of A to be 0. This is because step 2 created the static variables but they have only have default values. An int is a primitive so the default value is 0. The next to occur as part of step 3 is line 14 which sets the variable A to 15. Next the static block on lines 17 - 19 outputs the value of A. You can see the second output says that the value of A is now 15.
That ends step 3. The next part is that the main method is finally executed, which was called when the program started. I put the main method first just to prove that the static blocks and static variable initialization occurred before it, which if you look at the output line 3 doesn't show up until further down the output. Then the first object is created on line 4 which starts the steps of an object creation:
first the non-static variables are created and set to their default values. Then the non-static blocks and the lines of variables are executed in order from top to bottom. The first to occur is the non static block on lines 11-13. This outputs the value of B, which has the default value of 0. Next B is initialized. Then the block at lines 21-23 are executed which output that B is now 10.
0
Guadalupe Gagnon
19 April 2023, 15:58
I used the method getB(), which is required at the first block at lines 11-13. Because the code is pre-loaded into memory the method getB() can be used here while the using the variable B would result in an illegal forward reference and the code wouldn't compile. This is a quirk in Java. So I couldn't change the output at line 12 to:
I could, however, change the output on line 22 to output B without the method without this error occurring.
The same thing applies to the output on lines 8 and 18. Solution.A is required on line 8, but I could just use A on line 18. 0
Andreas Blank
19 April 2023, 16:14
Mate, I got so many questions that didn't get answered in this course... I feel overwhelmed. but you help me a lot. this nonstatic commands you wrote in the class (the prints)... When I write them without the curly braces to the class, the compiler got problems. So, I didn't even know that you can write such print commands into the class. Does this mean I can write any command to a regular class in curly braces and it will be executed sequentally as soon the class gets called through the constructor?
+1
Guadalupe Gagnon
19 April 2023, 16:14
I forgot one thing:
When an object is created the actual steps are:
1) The non-static fields are created and set to default values (0 for primitives and null for objects)
2) next the non-static fields and static blocks are executed in order from the top of the code to the bottom of the code. This is where they are initialized
3) the constructor is executed
0
Guadalupe Gagnon
19 April 2023, 16:20
So, I didn't even know that you can write such print commands into the class.
ya, i'm sorry. I went really deep into this. This stuff will be introduced to you later in the course more gradually. However I recommend that you pick up a good book on Java if you don't already have one to supplement your learning. The one I used, and can highly recommend, is "Thinking in Java" by Bruce Eckel. The 4th edition is free online: here is the link
This course is great with all the task, however they really don't explain a lot. That book taught me WAY more than the class lessons. I was reading it at the same time I was doing the course and it really helped me a lot.
0
Andreas Blank
25 April 2023, 14:31
Hello mate, I now understood everything but one little thing is still cryptical to me. I hope you can answer my question straight, which again refers to your example:
public class Solution {
static Solution test = new Solution();
static {
System.out.println("Printing A in static block: " + test.A);
}
static int A = test.B + 2;
int B = 5;
int C = A + B;
public static void main(String[] args) {
System.out.println("Printing A in main method: " + test.A);
System.out.println("test.C: " + test.C);
System.out.println("new Solution().C: " + new Solution().C);
}
}
You have given me the following algorithm regarding the static variables and blocks:
1) the entire class code is loaded into memory
2) next the static fields are created and set to default values (0 for primitives and null for objects)
3) next the static fields and static blocks are executed in order from the top of the code to the bottom of the code. This is where they are initialized
My question is, how can test.A (having the default value "0" due to inizialisation) be printed, since at this point the reference variable must, due to your algorithm, also be null? Isn't it at this point that the actual command then looks like "null.A" because the object variable "test" has been declared but not initialized due to your algorithm? How can "A" by called by the object variable being "null"? When I write this out this command for testing reasons, the compiler gives back an error.
+1
Guadalupe Gagnon
25 April 2023, 15:14
At step 2 the static variables have their default values.
Step 3 states that static variables AND static blocks are executed in order from top to bottom. This means they have the same priority and their execution order is determined by where they reside in the code.
So:
#1 you would first find the first static variable or block, which in this code is the static variable test, and that line is executed. To fully execute that line the object must be created, which kicks off the steps for object creation (non static variables are created, then non static variables and blocks are executed in order) which are fully completed before that line concludes. Remember that static variables belong to the class and not to any object, so creating the object for test does not move step 3 along any faster.
#2 The next line to be executed, according to the rules of step 3, is the line in the static block that outputs test.A. At this point the line that initializes A has not been reached so A is going to be 0, which is output.
#3 Now the final static variable line is reached, the line for A, and initialized to test.B + 2
+1
Guadalupe Gagnon
25 April 2023, 15:26
Here is another example that displays the steps a little deeper:
+1
Guadalupe Gagnon
25 April 2023, 15:34
- In this code, if we follow the steps, first the code is preloaded and then all the static variables are created and set to default values (steps 1 and 2)
- Next the first static block is run and this output the values of all the static variables, which for A will be 0 and test1/test2 will be null.
- Next test1 and test2 are initialized, which means that the steps for object creation are executed, which in this code is only the non-static block. You will see by the output that the non-static block is executed twice which makes sense since 2 objects are created.
- Next the second static block is reached and output that the value of A is now 2 and the values for test1/test2 have unique hash codes (something like Test.Solution@378bf509) where to the left of the @ symbol is the full class and package name of the object and to the right is the place in memory the object resides. This is default output for any object where you do not provide your own implementation for default output.
The value of A is 2 because the non-static block increases A by 1 (A++;) each time an object is created.
- Next the line for the A is reached and executed, which sets A to 5.
- next the third static block is reached and outputs A which, as said directly above, is 5.
That is the abbreviated step by step execution. I designed the output to showcase this order. Run it and check the output and see if you can understand the way the code flows.
+1
Andreas Blank
26 April 2023, 10:05
I understand, but this still leaves out the question why A could be called by the object "test" which along your algorithm should not be initialized by that point... but should be "null". Please see this code:
static Solution test;
static {
System.out.println("Printing A in static block: " + test.A);
System.out.println(test+" Speicheradresse");
test = new Solution();
System.out.println(test+" Nach initialisieren");
}
static int A = test.B + 2;
So, step one: the static variables including A and test are created and set to default values... A should be 0 and test should be null at this point. Next, the static fields and blocks are executed. This means " System.out.println("Printing A in static block: " + test.A);" gets executed before "test" gets initialized. How can test.A work when it is actually null.A at this point, since "test" is not initialized? Because test.A at this points still gives back the default value "0" of the variable "A". Can you please explain this exact point to me?
+1
Guadalupe Gagnon
26 April 2023, 13:34
The variable A is part of the class and not part of any object. When you call static variables you call them by the class name, the dot operator, and then the variable name. So:
Solution.A
would be proper. You can use a variable name to access static variables that belong in that class, such as is done by using the variable test, but the compiler will still access those variables by using the class type of that variable and not the actual variable. This means that the variable doesn't need to have an object initialized as the compiler still reads
test.A as Solution.A
If test is null then you would get a null pointer exception if you tried to access any of the object/instance variables in the class (the non-static ones).
+2
Andreas Blank
3 Mai 2023, 09:42
Thank you, my friend. You gave me good answers and helped a lot!
+1