static 변수의 메모리 구조를 다시 보던 중 궁금증이 생겼다.
static 변수를 클래스가 아닌 인스턴스를 통해 접근하면 힙 영역에서 메서드 영역으로 리턴되어 접근한다.(지양하는 방법)
즉, 여러개의 인스턴스를 만들어도 static변수는 결국 정적 변수(프로그램 실행 시점에 딱 만들어지고, 프로그램 종료 시점에 제거되는 변수)이므로 한 곳을 바라본다.
여러개의 인스턴스를 만들어 인스턴스를 통해 접근해도, 결국 클래스를 통해 접근하는 것과 같다.
하나의 인스턴스에서 값을 변경하면, 다른 인스턴스에서의 접근도 변경된 값을 갖는다.
//public static int cnt = 1 일 경우
Test t1 = new Test();
t1.cnt = 2;
Test t2 = new Test();
t2.cnt = 3;
System.out.println(t1.count); //3
System.out.println(t2.count); //3
// t1과 t2는 서로 다른 인스턴스임에도 불구하고 같은 값이 출력된다.
💡💡💡💡💡💡💡 여기서 생긴 궁금증!
static 변수의 값을 변경하면 위와 같은데, static 메서드를 재정의하는 경우는 어떠한가?
상속받은 static메서드를 오버라이딩 하는 경우 말이다.
오버라이딩이란?
부모 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.
👉 자세히 click
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
자식 클래스가 부모 클래스의 정적 메서드와 동일한 시그니처를 가진 정적 메서드를 정의하는 경우, 자식 클래스에서의 메서드는 부모 클래스의 메서드를 숨긴다.
'재정의'가 아닌 '은닉'이 이루어지는 것이다.
어떤 메서드가 은닉될지는 부모 클래스에서 호출되는지 혹은 자식 클래스에서 호출되는지에 따라 다르다.
public class Test {
public static void main(String[] args) {
Parant parent1 = new Parent();
Parant parent2 = new Child();
Child child = new Child();
parent1.getTest1(); //부모1 hiding 자식 메서드 은닉
parent1.getTest2(); //부모2
parent2.getTest1(); //부모1 hiding 자식 메서드 은닉
parent2.getTest2(); //자식2
child.getTest1(); //자식1 hiding 부모 메서드 은닉
child.getTest2(); //자식2
}
}
class Parent {
public static void getTest1() {
System.out.println("부모1");
}
public void getTest2() {
System.out.println("부모2");
}
}
class Child extends Parent {
public static void getTest1() {
System.out.println("자식1");
}
public void getTest2() {
System.out.println("자식2");
}
}
메서드 호출이 어느 객체로 전달될지 결정하는 과정을 Method Dispatch라 한다.
정적(static메서드)는 컴파일시 메모리에 올라간다.
정적 메서드는 클래스에 속한 메서드이기 때문에, 객체의 실제 타입이 아닌 참조 변수의 타입에 따라 호출된다.
즉, 오버라이딩처럼 런타임 시 인스턴스가 실제로 참조하고 있는 클래스를 찾아가는 것이 아니라 컴파일 시 결정된 클래스를 찾아가기 때문에 위와 같은 상황이 발생하는 것이다.
이쯤 왔으면 궁금증 이 생겼을 것이다.
왜 메서드 '은닉(hiding)'인가?
왜 '은닉'이라는 표현을 쓰는지 궁금졌다.
'A와 B에서 B가 A를 재정의 한 것'과
'A와 B에서 B가 A를 은닉 한 것'은 무슨 차이가 있는가?
'재정의(overriding)'는 부모 메서드를 말 그대로 다시 '재정의'하는 것이지만,
'은닉'은 자식 메서드가 새로 '추가'되어 부모 메서드를 '은닉(hide)' 시켜버리는 것이다.
부모의 정적메서드를 자식이 재정의하려고 하면, 자식 클래스는 재정의가 아닌 부모메서드를 '은닉'시키고(가려버리고) 새로 '추가'하게 된다. 이는 새롭게 추가된 것이며 서로 구별되어 진다.
(상속과 메모리 구조 포스팅 작성중입니다. 이후 링크와 함께 내용추가 예정입니다. 총총..)
https://docs.oracle.com/javase/tutorial/java/IandI/override.html
새로운 시리즈 <물음표 살인일지>를 만들었다.
나는 주변에서 물음표 살인마로 불리는데 호기심도 많고, 궁금한건 못참기 때문...
개발하면서 가졌던 (쓸데없을수도 있는)궁금증들을 적어보고자 한다.