기술 면접 대비겸 CS 지식 향상을 위해 정리하는 포스트.
자바는 JVM 위에서 동작하여 특정 운영체제에 종속되지 않는다. JVM에 대해서는 별도의 포스트로 정리할 예정.
GC가 대표적, 이도 따로 정리할 예정.
자바를 처음 공부하는 스터디에서 들었던 말이 생각난다. 자바는 개발자를 믿지 않아. 처음 42서울에서 C로 개발 공부를 시작하고, 자바를 공부할수록 그 말의 의미를 점점 더 깨달아가는 것 같다. 편리하지만 그만큼 추상화된 것들로 인해 어떻게 해야하지? 싶을 때도 있는 것 같다.
JVM, GC가 편의성을 가져다 준 만큼 그로 인한 속도 저하가 발생하기도 한다.
앞서 자바의 장점으로 객체 지향 언어를 꼽았는데, 그렇다면 과연 객체 지향 언어는 무엇인가? 내가 생각한 객체 지향이란 결국 하나의 고유한 특성을 가진 객체를 여러개 만들고 이 각 객체들이 서로 상호작용을 하도록 만든 것이라고 생각한다.
C의 경우 절차 지향 언어로 코드가 위에서부터 아래로 흐르게 된다. 따라서 코드의 순서가 중요하고, 프로그램이 커질 수록 유지보수가 어려워진다. 이에 반해 JAVA와 같은 객체 지향 언어는 누가 무엇을 할 것인가?를 중점으로 코딩을 하게 되고, 이에 따라 유지보수가 쉬워진다.
각 객체마다 고유의 멤버 변수, 멤버 함수들을 가질 수 있고 이를 통해 해당 객체가 할 역할을 한정해 줄 수 있게 된다. 그러다보니 어떤 객체의 행동이 변해야 할 때 해당 객체 내부만 수정하면 되고, 외부에는 영향을 미치지 않는다. 그래서 유지보수가 쉬워지는 것이다. c는 하나가 잘못 됐을 때 아 나 이거 어디까지 고쳐야 하지..? 하는 때가 더러있었는데, JAVA의 경우 그 대상을 찾기도, 한정짓기도 쉬워진다. 그러나 이를 위해서는 설계를 잘 해야한다!! 또한, 기계어에 조금 더 가까운 c가 처리 속도나, 실행 속도면에서 빠를 수밖에는 없다.
정보의 은닉이다. 각 객체의 멤버 변수와 메소드 등 실제 구현 내용을 외부로부터 감추는 것이다. 객체의 외부에서는 공개된 메소드를 통해서만 접근할 수 있다. 멤버 변수는 private으로 지정하고 외부에서는 getter, setter 등으로 접근하는 것이 예이다. 클래스화 하는 것과 동일.
상위 객체의 속성을 하위 클래스에 물려줄 수 있다. 이를 통해 코드의 중복을 줄일 수 있다.
상위 클래스의 메소드를 재정의하는 오버라이딩, 같은 메소드이나 다른 매개 변수를 통해 다르게 동작하도록 하는 오버로딩과 같은 구현이 가능하다.
실제 존재하는 대상에서 특징들을 뽑아내 프로그램으로 만드는 것이다.
[S]ingle responsibility principle - 단일 책임 원칙
한 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화 해야 함
[O]pen/closed principle - 개방/폐쇄 원칙
클래스, 함수 등은 확장에 대해 열려 있어야 하고, 변경에 대해서는 닫혀있어야 함
기존 코드를 수정하지 않고 기능을 수정하거나 추가할 수 있어야 하는 것
내가 변화하는 게 다른 객체에게 영향을 주는가? -> 결합도가 높다고 할 수 있음
변화되는 부분과 닫히는 부분이 분리가 되어야 한다[L]iskov subtitution principle - 리스코프 치환 원칙
프로그램의 정확성을 깨트리지 않으면서 하위 타입의 객체로 바꿀 수 있어야 함
자식 객체를 부모 객체로 변경해도 정삭 작동해야 하는 것
자바 컬렉션 프레임워크가 좋은 예[I]nterface segregation principle - 인터페이스 분리 원칙
큰 덩어리의 인터페이스를 구체적이고 작은 단위로 분리함으로써 클라이언트가 꼭 필요한 메서드만 이용할 수 있게 함
하나의 general한 인터페이스보다 여러개의 special한 인터페이스가 낫다는 것[D]ependency inversion principle - 의존 관계 역전 원칙
변화하기 쉬운 것 또는 자주 변화하는 것 보다는 변화하기 어려운 것, 거의 변화가 없는 것에 의존하도록 함
각 클래스간의 결합도를 낮추고, 구현 클래스에 의존하기보다 인터페이스에 의존하라는 것
구체 클래스 = 인스턴스화 할 수 있는 클래스(=new 할 수 있는 클래스)
<-> 인터페이스 & 추상클래스
힙, 메서드 영역은 전부 공유, Pc register&Stack&Native Method stack 영역은 각 쓰레드마다 생성
향후 JVM 포스트에서 말하는 것이 맞나 싶지만, 일단은!
.java 소스 코드 작성.java를 읽고 .class 바이트코드로 컴파일.class 바이트코드를 JVM의 클래스 로더에게 전달C, C++의 코드는 컴파일 시 바로 CPU에서 실행이 가능한 코드인 기계어로 변환되어 속도가 빠르지만, JAVA의 경우 byte code로 컴파일 후 그 byte code를 기계어로 변환하는 시간이 필요하여 수행 속도가 더 오래 걸린다
자바는 call by value라고 한다. 처음 call by reference 할 때 이거 c++ 참조자 말하는 거 맞나..? 싶었는데 찾아보니 맞는 것 같다. c++ 공부 당시에 c도 포인터로 나를 힘들게 하더니 이젠 참조자야 싶었던 기억이 난다. 그러니까, 당연히 포인터도 없는 java에서 참조자가 있을리 없기는 하다. 자바가 개발자가 맘대로 원본 값을 수정하게 뒀을리가 없음.. 처음 참조자에 대해 배웠을 때 매개변수로 넘기면서 복사 생성하지 않으니 메모리를 효율적으로 관리하기에 너무 좋겠다는 생각이 들었었다. 포인터 변수와 같이 변수를 위한 메모리 자체도 할당하지 않을 수 있다니! 그런데 다시 생각하면 위험도가 너무 높다. 원본값이 변경 될 수 있다는 것은 어딘가에서 치명적일 수 있게 마련일테니.