[java] 정적 수정자는이 코드에 어떤 영향을 미칩니 까?
내 코드는 다음과 같습니다.
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
-
두 번째 단계 인 실행 은 위에서 아래로 시작됩니다. Java에서 실행은 첫 번째 정적 멤버에서 시작됩니다.
여기서 첫 번째 정적 변수는static A obj = new A();
이므로 먼저 해당 변수의 객체를 만들고 생성자를 호출하므로num1
및 값num2
은1
.
그런 다음 다시static int num2=0;
실행되어num2 = 0;
.
이제 생성자가 다음과 같다고 가정합니다.
private A(){
num1++;
num2++;
System.out.println(obj.toString());
}
이것은 여전히 참조를 얻지 않았기 NullPointerException
때문에 던질 것 obj
입니다 class A
.
답변
어떤 static
수정 수단은 변수 선언인가 변수 클래스 변수보다는 인스턴스 변수이다. 즉 num1
, 변수 는 하나 뿐이고 변수 는 하나 뿐입니다 num2
.
(참고 : 정적 변수는 이름이 모든 곳에 표시되지 않는다는 점을 제외하면 일부 다른 언어의 전역 변수 와 같습니다 .로 선언 된 경우에도 public static
규정되지 않은 이름은 현재 클래스 또는 수퍼 클래스에서 선언 된 경우에만 표시됩니다. , 또는 정적 가져 오기를 사용하여 가져 오는 경우 차이입니다. 진정한 글로벌은 어디에서나 자격없이 볼 수 있습니다.)
당신이 참조 할 때 그래서 obj.num1
하고 obj.num2
, 실제로 언급하는 누구의 실제 명칭이다 정적 변수 와 . 마찬가지로, 생성자가 증가 할 때 와 ,이 (각각)과 동일한 변수를 증분한다.A.num1
A.num2
num1
num2
귀하의 예제에서 혼란스러운 주름은 클래스 초기화에 있습니다. 클래스는 먼저 모든 정적 변수를 기본값으로 초기화 한 다음 선언 된 정적 이니셜 라이저 (및 정적 이니셜 라이저 블록)를 클래스에 나타나는 순서대로 실행하여 초기화됩니다. 이 경우 다음이 있습니다.
static A obj = new A();
static int num1;
static int num2=0;
다음과 같이 발생합니다.
-
통계는 기본 초기 값으로 시작합니다.
A.obj
입니다null
및A.num1
/A.num2
제로입니다. -
첫 번째 선언 (
A.obj
)은의 인스턴스A()
와A
증분A.num1
및에 대한 생성자를 만듭니다A.num2
. 때 선언이 완료A.num1
하고A.num2
모두1
, 그리고A.obj
새롭게 구축 지칭A
예. -
두 번째 선언 (
A.num1
)에는 이니셜 라이저A.num1
가 없으므로 변경되지 않습니다. -
세 번째 선언 (
A.num2
)에는에 0을 할당하는 이니셜 라이저가A.num2
있습니다.
따라서 클래스 초기화의 끝에서 A.num1
is 1
and A.num2
is 0
… 그리고 이것이 print 문이 보여주는 것입니다.
이 혼란스러운 동작은 실제로 정적 초기화가 완료되기 전에 인스턴스를 만들고 사용중인 생성자 가 아직 초기화되지 않은 정적 에 의존 하고 수정 한다는 사실에 있습니다. 이것은 실제 코드에서 피해야 할 일입니다.
답변
1,0이 맞습니다.
클래스가로드되면 모든 정적 데이터가 선언되어 초기화됩니다. 기본적으로 int는 0입니다.
- 먼저 A가 생성됩니다. num1 및 num2가 1과 1이 됨
static int num1;
아무것도하지 않는 것보다- 보다
static int num2=0;
이 NUM2에 0을 기록
답변
이는 정적 이니셜 라이저의 순서 때문입니다. 클래스의 정적 표현식은 하향식 순서로 평가됩니다.
호출 내지 제의 생성자 A
된 세트 num1
및 num2
1 모두 :
static A obj = new A();
그때,
static int num2=0;
호출되고 num2 = 0으로 다시 설정됩니다.
그래서 num1
1이고 num2
0입니다.
참고로 생성자는 정적 변수를 수정해서는 안됩니다. 이는 매우 나쁜 설계입니다. 대신 Java에서 Singleton 을 구현 하는 다른 접근 방식을 시도하십시오 .
답변
JLS의 섹션은 §12.4.2 에서 찾을 수 있습니다 .
자세한 초기화 절차 :
9. 다음으로, 클래스의 클래스 변수 이니셜 라이저와 정적 이니셜 라이저 또는 인터페이스의 필드 이니셜 라이저를 텍스트 순서 로 실행합니다. 단, 최종 클래스 변수와 값이 컴파일되는 인터페이스의 필드는 예외입니다. -시간 상수가 먼저 초기화됩니다.
따라서 세 개의 정적 변수는 텍스트 순서로 하나씩 초기화됩니다.
그래서
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;
주문을 다음과 같이 변경하는 경우 :
static int num1;
static int num2=0;
static A obj = new A();
결과는입니다 1,1
.
(가) 있습니다 static int num1;
때문에 초기화 변수가되지 않습니다 ( §8.3.2 ) :
필드 선언자에 변수 이니셜 라이저가 포함 된 경우 선언 된 변수에 대한 할당 (§15.26)의 의미를 가지며 선언자가 클래스 변수 (즉, 정적 필드)를위한 것이라면 변수 이니셜 라이저는 다음과 같습니다. 클래스가 초기화 될 때 평가되고 할당이 정확히 한 번 수행됨
그리고이 클래스 변수는 클래스가 생성 될 때 초기화됩니다. 이것은 먼저 발생합니다 ( §4.12.5 ).
프로그램의 모든 변수에는 값이 사용되기 전에 값이 있어야합니다. 각 클래스 변수, 인스턴스 변수 또는 배열 구성 요소는 생성 될 때 기본값으로 초기화됩니다 (§15.9, §15.10) : 유형 바이트의 경우 기본값 즉, (byte) 0의 값입니다. short 유형의 경우 기본값은 0, 즉 (short) 0의 값입니다. int 유형의 경우 기본값은 0, 즉 0입니다. long 유형의 경우 기본값은 0, 즉 0L입니다. float 유형의 경우 기본값은 양수 0, 즉 0.0f입니다. double 유형의 경우 기본값은 양수 0, 즉 0.0d입니다. char 유형의 경우 기본값은 널 문자, 즉 ‘\ u0000’입니다. 부울 유형의 경우 기본값은 false입니다. 모든 참조 유형 (§4.3)의 경우 기본값은 null입니다.
답변
이런 식으로 생각하면 도움이 될 것입니다.
클래스는 객체의 청사진입니다.
개체는 인스턴스화 될 때 변수를 가질 수 있습니다.
클래스는 변수를 가질 수도 있습니다. 이들은 정적으로 선언됩니다. 따라서 개체 인스턴스가 아닌 클래스에 설정됩니다.
응용 프로그램에서 모든 클래스 중 하나만 가질 수 있으므로 해당 클래스를위한 전역 저장소와 비슷합니다. 물론 이러한 정적 변수는 애플리케이션의 어느 곳에서나 액세스하고 수정할 수 있습니다 (공용이라고 가정).
다음은 정적 변수를 사용하여 생성 된 인스턴스 수를 추적하는 “Dog”클래스의 예입니다.
“Dog”클래스는 클라우드이고 주황색 상자는 “Dog”인스턴스입니다.
도움이 되었기를 바랍니다!
퀴즈처럼 느껴진다면이 아이디어는 Plato 가 처음 소개 한 것입니다.
답변
static 키워드는 주로 메모리 관리를 위해 Java에서 사용됩니다. 변수, 메서드, 블록 및 중첩 클래스에 정적 키워드를 적용 할 수 있습니다. static 키워드는 클래스의 인스턴스보다 클래스에 속합니다. static 키워드에 대한 간략한 설명은 다음과 같습니다.