- 자바의 구조 이해하기
모든 컴퓨터 언어는 기계어에서 시작되었고 어셈블리어 C를 거쳤다. 자바 또한 마찬가지이고 C의 특징을 완전히 지우지 못했다. 자바가 아무리 객체지향 언어라도 절차지향의 흔적이 남아있다는 것이다.
이런 이야기를 하는 이유는 나는 코드를 작성할 때마다 메서드를 호출하고 객체를 만들고 인스턴스를 참조 하는 과정에서 컴퓨터가 지금 어디를 연산하고 있는지 어느 메모리에서 일을 하는지를 정확하게 이해하지 못해 곤란했던 적이 많았다. 그렇기에 자바의 시작 개념을 공부하며 개념을 다시 다졌다.
먼저 JVM, JDK, JRE 등이 시작하는 과정에서의 T메모리에 대한 개념이다.
pulic calss Start{
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
public class Main {
public static void main(String[] args) {
int i = 0;
int k = 20;
if (i == 10) {
int m = k + 5;
k = m;
} else {
int p = k + 10;
k = p;
}
// k = m + p; 오류 발생
}
}
일단 else {} 부분은 생기지도 않는다. 나는 그냥 코딩을 하면 if else 두개다 생기고 하나만 사용하는 줄 알았다. 그리고 main() 스택 프레임 안에 if(true) 스택 프레임이 생기는 것이다. 스택 프레임은 전부 다 따로 생길거라는 생각과는 많이 달랐다.
외부 스택 프레임에서 내부 스택 프레임의 변수에 접근하는 것은 불가능하나 역은 가능하다.
public class Main {
public static void main(String[] args) {
int k = 5;
int m;
m = square(k);
}
private static int square(int k) {
int result;
k = 25;
result = k;
return result;
}
}
스태틱 영역의 클래스안에 static 메소드가 인자값을 가지고 생성된다.
메서드를 호출하는 과정에서 스택프레임이 따로 생성되었다. 위의 경우와는 다르게 서로 접근하지 못하나 시간의 순서에 따라 진행하면서 square() 스택 프레임이 사라지면 반환값을 전달해 준다.
코드를 작성하다 보면 변할 것처럼 보이는 변수가 변하지 않거나 변하지 않아야 하는 변수가 변하는 경우가 있는데 이를 보며 확실하게 알게 되었다.
public class Mouse{
public String name;
public int age;
public int countOfTail;
public void sing(){
System.out.println("찍찍");
}
public class MouseDriver {
public static void main(String[] args) {
Mouse mickey;
mickey = new Mouse();
mickey.name = "미키";
mickey.age = 85;
mickey.countOfTail = 1;
mickey.sing();
}
}
JVM이 Mouse클래스를 static영역에 생성하고 변수를 만들어주고 이를 통해서 힙 영역에 인스턴스를 생성한다.
인스턴스를 가비지 컬렉터가 수거한다는 의미를 알게되었는데 만약 mickey = null;을 넣게 되면 참조변수 mickey의 화살표가 사라지게 되면서 인스턴스는 아무와도 연결이 되지 않는 상태가 되는데 이 상황을 두고 인스턴스가 사라지면서 가비지 컬렉터가 수거를 하게 되는 상황이라고 한다. (물론 언제 수거하는 지는 알 수 없다.)
public class Animal {
public String name;
public void showName(){
System.out.printf("안녕 나는 %s야 반가워\n", name);
}
}
public class Penguin extends Animal {
public String habitat;
public void showHabitat(){
System.out.printf("%s는 %s에 살고 있어\n", name, habitat);
}
//////////////////////////////////////////////////////
@Override
public void showName() {
System.out.println("나는 펭귄이야");
}
public void showName(String yourName) {
System.out.printf("%s야 안녕 나는 %s라고 해", yourName, name);
}
}
public class Driver {
public static void main(String[] args) {
Penguin pororo = new Penguin();
pororo.name = "뽀로로";
pororo.habitat = "남극";
pororo.showName();
pororo.showHabitat();
Animal pingu = new Penguin();
pingu.name = "핑구";
// pingu.habitat = "EBS";
pingu.showName();
// pingu.showHabitat();
// Penguin pengsoo = new Animal();
/////////////////////////////////////////////
pororo.showName();
pororo.showName("루피");
pororo.showHabitat();
pingu.showName();
}
}
상위 인스턴스가 생성되고 하위 인스턴스가 생성된다는 잘 알고 있지만
하위클래스 변수 = new 상위클래스(); 의 형식에서 많이 고통받았기에 이런 방식으로 그림으로 표현해보니 한층 더 알기 쉬워졌다.
내가 사용할 수 있는 함수와 속성을 정확하게 알게 되었다.
오버라이딩은 사실 vtable에 의해 이루어져 있으나 편의상 이렇게 그림을 그린 것 같았다. 자바를 이해하는 데는 문제가 없는 것 같다.(오히려 vtable보다 훨씬 이해가 잘된다.
오버로딩은 굳이 용어를 붙어야 할 정도로 그냥 아예 다른 메서드이다. 그냥 인간의 관점에서 같아 보이는 것이지 그냥 별개의 메서드이다.
하루에 1~2 문제는 풀어야지 하는 약속을 안지켰다. 그냥 하루에 몰아서 10문제 정도 풀었는데 기억나는 것은 약간 꼼수?라고 해야하나 다른 개념이라고 해야하나 잘 모르겠으나 배열과 관련된 개념이었다.
보통 뭔가 숫자를 받거나 갯수를 세어서 반영한다거나 하는 경우에 int[]만을 활용했는데 결국 결과 값으로 들어 있느지 없느지에 대한 boolean을 받는 경우에 그냥 boolean[]으로 배열을 만드는 것이었다. 코드 길이가 엄청 줄고 시간도 단축되고 메모리도 덜 사용하는 점에서 좋은 것 같기는 한데 개발을 한다는 생각에서는 int[]형으로 푸는 것이 맞는지 고민된다.
🛑 자바 개념관련해서 이해 하고 정리하는 과정에서 좀 문제가 많았다. 알고 있다 확실히 알고 있다의 차이를 좁혀가는 과정이 쉽지는 않다.
🛑 코딩 테스트 문제를 좀 더 풀어야 할 것 같고 알고리즘도 강의만 듣지 말고 조금은 풀어봐야 할 것같다. 비효율적인 코딩을 좀 자주 하게 되는 것 같다.
✅ 스프링을 들어가기전에 자바를 다시 다지는 과정이 꽤나 유익했다. 코딩할 때 "이게 되나?" 하고 여러번 돌려보고 작성했는데 이제는 그럴 일이 많이 줄어들 것 같다. 또 클래스를 잘 만들 수 있을 것 같다.
✅ 메모리에 관해 한번 정리하는 글을 쓰고 싶었는데 이번에 작성하게 되어 미룬 숙제를 해결하여 마음이 편해졌다. 코딩테스트도 좀 미루지 말아야겠다.
😃 확실하게 한번 정리하는 과정이 쉽지는 않았지만 얻어간 것이 있는 한주 였기에 기분이 좀 났다. 스프링을 공부하려고 했다가 시간 낭비를 많이 해봤기에 이런 공부만 있으면 좋겠다고 생각한다.
😢 스프링 공부를 조금씩 하고는 있는데 여전히 뭔 소린지 모르겠다. 강의마다 죄다 생략하는 부분도 많고 그냥 다 던져버리고 싶다. "일단 따라서 해보고 후에 설명하겠다" 하면서 이후에 설명은 내 수준으로 안해준다. 이번에도 다른 강의를 찾아서 그 강의를 통해서 해볼 예정이고 다른 책을 볼 예정이다.(사실 책은 안정했다. 책이 너무 많고 어렵다.)