정적 수정자는이 코드에 어떤 영향을 줍니까?
내 코드는 다음과 같습니다.
class A {
static A obj = new A();
static int num1;
static int num2=0;
private A() {
num1++;
num2++;
}
public static A getInstance() {
return obj;
}
}
public class Main{
public static void main(String[] arg) {
A obj = A.getInstance();
System.out.println(obj.num1);
System.out.println(obj.num2);
}
}
출력은 1 0
이지만 이해할 수 없습니다.
누군가 나에게 설명 할 수 있습니까?
Java에서는 두 단계가 발생합니다. 1. 식별, 2. 실행
식별 단계 에서는 모든 정적 변수가 감지되고 기본값으로 초기화됩니다.
이제 값은 다음과 같습니다.
A obj=null
num1=0
num2=0
두 번째 단계 인 execution 은 위에서 아래로 시작합니다. Java에서는 첫 번째 정적 멤버부터 실행이 시작됩니다.
여기서 첫 번째 정적 변수는static A obj = new A();
이므로 먼저 해당 변수의 객체를 만들고 생성자를 호출하므로num1
및 의 값이num2
됩니다1
.
그리고 다시static int num2=0;
실행됩니다num2 = 0;
.
이제 생성자가 다음과 같다고 가정하십시오.
private A(){
num1++;
num2++;
System.out.println(obj.toString());
}
This will throw a NullPointerException
as obj
still has not got a reference of class A
.
What the static
modifier means when applied to a variable declaration is that the variable is a class variable rather than an instance variable. In other words ... there is only one num1
variable, and only one num2
variable.
(Aside: a static variable is like a global variable in some other languages, except that its name is not visible everywhere. Even if it is declared as a public static
, the unqualified name is only visible if it is declared in the current class or a superclass, or if it is imported using a static import. That's the distinction. A true global is visible without qualification anywhere.)
So when you refer to obj.num1
and obj.num2
, you are actually referring to the static variables whose real designations are A.num1
and A.num2
. And similarly, when the constructor increments num1
and num2
, it is incrementing the same variables (respectively).
The confusing wrinkle in your example is in the class initialization. A class is initialized by first default initializing all of the static variables, and then executing the declared static initializers (and static initializer blocks) in the order that they appear in the class. In this case, you have this:
static A obj = new A();
static int num1;
static int num2=0;
It happens like this:
The statics start out with their default initial values;
A.obj
isnull
andA.num1
/A.num2
are zero.The first declaration (
A.obj
) creates an instance ofA()
, and the constructor forA
incrementsA.num1
andA.num2
. When the declaration completes,A.num1
andA.num2
are both1
, andA.obj
refers to the newly constructedA
instance.The second declaration (
A.num1
) has no initializer, soA.num1
doesn't change.The third declaration (
A.num2
) has an initializer that assigns zero toA.num2
.
Thus, at the end of the class initialization, A.num1
is 1
and A.num2
is 0
... and that's what your print statements show.
This confusing behaviour is really down to the fact that you are creating an instance before the static initialization has completed, and that the constructor you are using depends on and modifies a static that is yet to be initialized. This something that you should avoid doing in real code.
1,0 is correct.
When the class is loaded all static data is initialized in oder they are declared. By default int is 0.
- first A is created. num1 and num2 becoming 1 and 1
- than
static int num1;
does nothing - than
static int num2=0;
this writes 0 to num2
It is due to the order of the static initializers. Static expressions in classes are evaluated in a top-down order.
The first to be called is the constructor of A
, which sets num1
and num2
both to 1:
static A obj = new A();
Then,
static int num2=0;
is called and sets num2=0 again.
That is why num1
is 1 and num2
is 0.
As a side note, a constructor should not modify static variables, that is very bad design. Instead, try a different approach to implementing a Singleton in Java.
A section in JLS can be found: §12.4.2.
Detailed Initialization Procedure:
9.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, except that final class variables and fields of interfaces whose values are compile-time constants are initialized first
So the three static variable will be initialized one by one in textual order.
So
static A obj = new A();
//num1 = 1, num2 = 1;
static int num1;
//this is initilized first, see below.
static int num2=0;
//num1 = 1, num2 = 0;
If I change the order to:
static int num1;
static int num2=0;
static A obj = new A();
The result will be 1,1
.
Note that the static int num1;
is not a variable initializer because(§8.3.2):
If a field declarator contains a variable initializer, then it has the semantics of an assignment (§15.26) to the declared variable, and: If the declarator is for a class variable (that is, a static field), then the variable initializer is evaluated and the assignment performed exactly once, when the class is initialized
And this class variable is initialized when the class is created. This happens first(§4.12.5).
Every variable in a program must have a value before its value is used: Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10): For type byte, the default value is zero, that is, the value of (byte)0. For type short, the default value is zero, that is, the value of (short)0. For type int, the default value is zero, that is, 0. For type long, the default value is zero, that is, 0L. For type float, the default value is positive zero, that is, 0.0f. For type double, the default value is positive zero, that is, 0.0d. For type char, the default value is the null character, that is, '\u0000'. For type boolean, the default value is false. For all reference types (§4.3), the default value is null.
Maybe it will help to think of it in this way.
Classes are blueprints for objects.
Objects can have variables when they are instantiated.
Classes can also have variables. These are declared as static. So they are set on the class rather than the object instances.
You can only every have one of any class in an application so it's kind of like global storage specifically for that class. These static variables can of course be accessed and modified from anywhere in your application (assuming they are public).
Here is and example of a "Dog" class that uses static variable to track the number of instances it has created.
"Dog" class is the cloud while the Orange boxes are "Dog" instances.
Hope this helps!
If you feel like some trivia, this idea was first introduced by Plato
The static keyword is used in java mainly for memory management. We may apply static keyword with variables, methods, blocks and nested class. The static keyword belongs to the class than instance of the class.For brief explanation about static keyword :
http://www.javatpoint.com/static-keyword-in-java
Many of the answers above are correct. But really to illustrate what is happening I've made some small modifications below.
As mentioned multiple times above, what's happening is a instance of class A is being created before class A is fully loaded. So what is considered the normal 'behavior' is not observed. This is not too dissimilar to calling methods from a constructor that can be overridden. In that case, instance variables may not be in an intuitive state. In this example class variables are not in an intuitive state.
class A {
static A obj = new A();
static int num1;
static int num2;
static {
System.out.println("Setting num2 to 0");
num2 = 0;
}
private A() {
System.out.println("Constructing singleton instance of A");
num1++;
num2++;
}
public static A getInstance() {
return obj;
}
}
public class Main {
public static void main(String[] arg) {
A obj = A.getInstance();
System.out.println(obj.num1);
System.out.println(obj.num2);
}
}
Output is
Constructing singleton instance of A
Setting num2 to 0
1
0
java does not initializes the value of any static or non static data member till it is not called but it creates it.
so So that here when num1 and num2 will be called in main then it will get initialized with values
num1 = 0+1; and
num2=0;
참고URL : https://stackoverflow.com/questions/20115672/how-does-the-static-modifier-affect-this-code
'developer tip' 카테고리의 다른 글
Maven의 샘플 settings.xml (0) | 2020.08.04 |
---|---|
SQL Output 절이 삽입되지 않은 열을 반환 할 수 있습니까? (0) | 2020.08.04 |
원격 Git 저장소 롤백 (0) | 2020.08.04 |
엔터티 프레임 워크에서 대량 삽입 성능 향상 (0) | 2020.08.03 |
Swift를 사용하여 프로그래밍 방식으로 UILabel을 만드는 방법은 무엇입니까? (0) | 2020.08.03 |