16일차 - 자바의 역사, JIT 컴파일러, HotSpot, Clone(), Type Erasure, wildcard, 조합 등
- -
🚀 학습 목표 & 예상 결과
- 자바의 신 18~19장 읽기 2시간 30분(5) -> 4시간 30분
- 멘토링 3주차 문제 풀기 4시간(8) -> 3시간 30분 (중간까지만 풀었다)
- 알고리즘 문제 2개 풀기 3시간(6) X
📌TIL
18장 - 자바의 신 1권 요약
객체지향 관련 용어들 정리 - 금일 작성한 포스팅 참고
패키지와 import, 자바에서 사용되는 타입과 종류, 변수의 종류, 연산자 종류, 조건문 등등..
현재까지 배운 내용(정리한 내용)들의 요약본이어서 인상적인 내용을 제외하곤 작성은 생략하겠다.
- throw : 예외 객체를 던지기 위해서 사용 (예외를 만든다.)
- throws : 예외 객체가 발생하면 던질 것이라고 메소드 선언 시 사용. (메소드를 호출한 곳으로 떠넘긴다.)
- Object의 주요 메소드
- clone() : 객체의 복사본을 만들어 리턴
- equals() : 현재 객체와 매개 변수로 넘겨받는 객체가 같은지 확인
- finalize() : 현재 객체가 쓸모 없어졌을 때 GC에 의해서 이 메소드가 호출된다.
- getClass() : 현재 객체의 클래스를 리턴
- hashCode() : 객체에 대한 해시 코드 값을 리턴
- String toString() : 객체를 문자열로 표현하는 값을 리턴
- wait(), notify(), notifyAll() : 스레드 처리 시 사용하는 메소드
- String의 주요 메소드, 어노테이션과 메타 어노테이션 - (14일 차 글 참고)
18장 이후, 중간점검
대답하지 못한 질문들을 모아 왔습니다.
- 형변환을 사용해야 하는 이유가 무엇인가요?
데이터 타입이 서로 다른 경우, 또는 다른 형태로 처리해야 할 경우 동일한 데이터로 만들어야 하기 때문입니다.
그 외엔 메모리를 절약하거나 객체의 다형성을 형성하는 데 사용되기도 합니다.
- 패키지를 선언하는 위치와 이름을 지정할 때의 유의점을 정리해 주세요.
동일한 패키지 명을 가진 다른 패키지가 존재하지는 않는지, 소문자로 작성되었는지를 확인해야 하며,
디렉터리 구조가 일치한 위치에 배치됐는지를 확인해야 합니다.
- static import는 무엇인지 정리해 주세요.
본래 import를 통해 접근할 때는 클래스이름을 통해 접근해야 하지만, static import를 하면 패키지명을 생략하고 멤버변수를 직접 사용할 수 있게 됩니다.
참고로 이건 컴파일러가 제공하는 편의성 기능입니다.
[컴파일 전 - 직접 작성한 코드]
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
public class MyClass {
public static void main(String[] args) {
double circumference = 2 * PI * radius;
double squareRoot = sqrt(16.0);
}
}
[컴파일 후 - JDK의 javac(자바 컴파일러)가 컴파일하며 수정한 코드]
import java.lang.Math;
public class MyClass {
public static void main(String[] args) {
double circumference = 2 * Math.PI * radius;
double squareRoot = Math.sqrt(16.0);
}
}
- instanceof 라는 연산자의 용도를 정리해 주세요.
instanceof는 객체가 특정 클래스에 속하는지의 여부를 boolean으로 리턴하는 메소드로, 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻합니다.
형변환을 시킬 수도 있고, 상위 클래스(분류)에따라 다른 처리를 하도록 만들 수도 있습니다.
다만, instanceof를 잘못 이용할 경우 (상위 클래스의 종류에 따라 처리를 다르게 하는 방식으로 작성한다던가) 유지보수에 문제를 일으키거나 캡슐화를 깨뜨릴 수 있으니 조심해야 합니다.
- 변수를 static으로 선언하는 것에 어떤 의미가 있는지 정리해 주세요.
인스턴스를 생성하지 않고도 클래스 이름을 통해 직접적인 접근이 가능하고, 한 번 초기화되면 값이 변하지 않는 특징을 가지고 있습니다.
모든 인스턴스가 공유하는 변수를 만듦으로써, 공통적으로 사용되는 값을 저장하기 위해 사용됩니다.
- 메소드를 static으로 선언하는 것에 어떤 의미가 있는지 정리해 주세요.
인스턴스를 생성하지 않고도 클래스 이름을 통해 직접적인 접근이 가능하고,
객체의 상태에 의존하지 않는 독립적인 동작(정렬 알고리즘, 문자열 조작, 수학 계산 등등)을 수행하거나 클래스 수준에서 공유되는 데이터를 저장하기 위해 사용됩니다.
예를 들어, Math의 PI나 sqrt() 같은 메소드는 굳이 객체를 생성하고 실행할 필요가 없기에 static으로 사용하는 것이 효율적이죠.
19장 - 자바의 역사와 JVM
- 1991년 "Green"이라는 프로젝트를 통해 자바의 모태가 탄생하기 시작.
- 제임스 고슬링(James Gosling), Mike Sheridan, Patrick Naughtom 3명의 젊은이가 시작한 프로젝트.
- 제임스 고슬링은 자바가 Oracle로 넘어가기 전까지 함께한 분으로, 중요한 분이다.
- 1992년 참나무를 보고 "Oak"라는 언어로 만들었다.
- 1995년 Oak의 이름이 Java로 변경되기 시작하면서 자바가 시작.
- 1996년 JDK 1.0 출시. JDK = Java Development Kit.
- 1998년 12월 Java -> J2SE (Java 2 Standard Edition = JDK를 의미)
- 2006년 Java SE 6 출시
- 2011년 Java SE 7 탄생 [Oracle이 인수]
- 2014년 3월 Java SE 8 정식릴리즈
- Java는 Oracle에서만 만드는 것이 아니다.
- IBM과 HP는 별도의 운영체제를 갖고 있으며, 그 OS에 최적화된 JDK를 개발하여 사용한다.
- Java 버전에서 제공되어야 하는 표준 문서가 만들어지면 각 기준에 해당하는 JDK가 별도로 만들어지는 것.
- 각 회사별 JDK의 내부 동작 구조는 상이하다.
- OpenJDK -> 소스에 라이선스 문제가 되는 부분을 완전히 제거한 오픈소스. 설치가 까다롭다. 우분투라는 리눅스 OS에 기본적으로 설치되어 있다.
- JRockit -> WebLogic이라는 WAS의 성능 최적화를 위해 만든 JDK. BEA라는 회사가 만들어 판매하다가 Oracle로 넘어갔다. (Oracle JDK에서 JRockit에서 사용하는 툴도 사용 가능해졌다.)
- JDK : Java Development Kit
- JRE : Java Runtime Environment
- 실행을 위한 환경. JRE만 설치하면 자바 컴파일 등의 각종 프로그램이 제외된 상태로 설치된다.
- J2SE : Java 2 Standard Edition
- Java SE : Java Standard Edition
- 2가 빠진 것은 SE 6부터이며, 쉽게 부를 수 있도록 변경한 것이다.
JIT 컴파일러
- Just-In-Time의 약자로 동적변환을 한다는 건데, 변환 작업은 인터프리터에 의해서 지속적으로 수행되나 필요한 코드의 정보는 캐시에 담아두었다가 재사용하는 형식을 취한다.
- 반복적으로 수행되는 코드는 매우 빠른 성능을 보이지만, 처음 시작할 때에는 변환 단계를 거쳐야 하므로 성능이 느려진다.
HotSpot?
- 다양한 JIT 컴파일러의 종류 중 Oracle에서 개발한 JIT 컴파일러다.
- HotSpot 컴파일러의 종류는 두 개다.
- HotSpot Client Compiler
- 단일 코어를 사용하는 사용자를 위해 만들어진 컴파일러로, 시작 시간을 빠르게 하고 적은 메모리를 점유하는 것을 목표로 한다.
- 실행 속도 향상을 위해 일부 최적화를 제한하며 실행된다.
- 윈도우에서는 java -server를 호출하지 않는 이상 기본적으로 해당 컴파일러로 실행하게 된다.
- HotSpot Server Compiler
- 애플리케이션의 전체 코드를 분석하고, 오랜 시간 동안 실행되는 애플리케이션의 장기적인 최적화를 목표로 하는 컴파일러다.
- 코드 크기와 메모리 사용량보다는 실행 속도를 우선시하며, 성능을 극대화한다.
- 2개 이상 물리적 프로세서와 2GB 이상의 물리적 메모리가 있으면 자동으로 해당 클라이언트로 시작된다.
- HotSpot Client Compiler
멘토링 문제 답변하며 얻은 지식
- Clone() 복제 방식에는 두 가지 종류가 존재한다.
- 얕은 복사 : 객체의 주소값을 가진 stack을 복제한다.
- 깊은 복사 : Heap 영역에 저장된 객체 자체를 복제한다.
- 사용하려면 오버라이딩을 해야 하며, 기본적으론 얕은 복사를 지원하고 깊은 복사로도 만들 수 있다.
- 추상클래스를 구현할 때는 구현된 메소드가 포함돼 있다고 하더라도, extends가 아닌 implements을 사용한다.
- Constant Pool
- 중복되는 상수 값을 저장하지 않음으로써 메모리를 절약하고, 필요시 Constant Pool에서 직접 참조돼 런타임시 성능이 개선된다.
- 자바에서 상수와 리터럴 값들을 저장하는 테이블로 메소드 영역에 각 클래스 별로 존재한다.
- 클래스 파일이 로드될 때마다 생성되고 유지되며, 클래스의 생명주기와 동일하다. (해당 클래스가 언로드 되거나 JVM이 종료될 때까지 메모리에 남아있다.)
- Enum 상수들은 Enum 클래스 파일의 Constant Pool에 저장된다.
- Type Erasure
- 제네릭을 걸어 사용한 변수를, 컴파일 과정 중 제네릭을 삭제하는 것을 말한다. (타입을 소거한다.)
- 모든 제네릭 타입은 컴파일 시 Object 타입으로 변환돼, 제네릭을 사용하지 않는 버전에서도 호환과 이식이 가능해지는 도움을 준다.
- 이 때문에 런타임 과정에서 타입 정보를 확인할 수 없게 되어, 타입 소거의 제약을 인지하고 제네릭 코드를 작성해야 한다는 제약이 걸리기도 한다.
- 제네릭이 나온 이유
- 컬렉션 클래스나 데이터 구조를 다룰 때 컴파일러가 타입 체크를 제대로 수행하지 못해, 런타임 시에 예기치 못한 타입 관련 오류가 발생하거나 수동으로 타입을 변환시켜줘야 하는 귀찮음이 있었기 때문.
- 제네릭 장단점
- 장점 : 타입이 안정되어 예상치 못한 타입 오류를 최대한 막아주고 일일이 형변환을 시켜줘야 하는 번거로움을 없앴으며, 가독성이 증가해 유지보수성이 향상됐다.
런타임 시에는 타입이 사라지기에 모든 오류를 막아주진 못하지만, 컴파일을 진행하며 문제가 생길 수 있는 부분들은 잡아주기에 많은 오류를 막아주는 것. - 단점 : 메모리 사용량이 비교적 증가했고 처음에 배우기 힘들다. 또 기본 자료형을 제네릭으로 사용하는 것, static 필드와 메소드에 제네릭을 사용하는 것이 불가능하다
- 장점 : 타입이 안정되어 예상치 못한 타입 오류를 최대한 막아주고 일일이 형변환을 시켜줘야 하는 번거로움을 없앴으며, 가독성이 증가해 유지보수성이 향상됐다.
- wildcard
- 제네릭 클래스 또는 매개변수나 리턴타입에 '알 수 없는 타입'을 명시하는 특별한 기호.
- 종류는 3가지다
- ? (Unbound) : 모든 타입을 나타낸다
- ? extends 클래스명 (Upper bound) : 클래스명을 상속하는 모든 자식 클래스를 나타낸다.
- ? super 클래스명 (Lower bound) : 클래스명의 모든 부모 클래스를 나타낸다.
- OOM : Out Of Memory Error의 약자로 메모리가 부족해 발생한 에러다.
- Immutable Class (불변클래스) : 객체를 생성 후, 외부에 의해 객체의 상태를 바꿀 수 없는 것을 말하는데 heap 영역에 저장된 객체의 데이터 자체를 변화시킬 수 없다는 뜻이다. 대표적으로 String이 있다.
- 상속보다 조합(Composition)을 사용해야 하는 이유
- 조합이란?
- 기존 클래스가 새로운 클래스의 구성요소로 쓰이는 것.
- 새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 가지는 것을 말한다.
- 상속의 문제
- 상위 클래스의 구현이 하위 클래스에게 노출되어 캡슐화를 깨뜨린다.
- 부모 클래스가 변경될 때 자식클래스도 수정해야 하는 일이 생기기도 한다.
- 해결 방안
- 메소드를 호출하기에 캡슐화를 깨뜨리지 않는다.
- 기존 클래스의 변화에 영향이 적어진다. (수정이 필요 없거나, 최소화시킬 수 있다.)
- 조합이란?
🔗 Feedback
◾ 예상 결과 <> 실제 결과
- 예상 결과 > 실제 결과
알고리즘 때문에 예상 결과가 처참해졌고, 전체적으로 조금 과대평가하기도 했다.
항상 예상결과가 더 높은 이유를 추적해 봤는데,
내가 실제 계획한 공부량보다 더 많은 양을 공부해 시간을 추가로 잡아먹게 되는 것 같다.
이해가 되지 않는 내용이나 추가적으로 궁금해진 사안을 그때그때 찾아보다 보니 전체적인 공부 시간이 늘어나는 것이다.
결국엔 공부를 제대로 많이 하는 것이 목표이기에 방식 자체가 나쁘다는 생각은 없는데, 추적이 불가능하단 점에선 단점이 있는 듯하여 어떻게 할지 고민 중이다.
일단 오늘은 머리를 많이 써서 고민을 하지 않으려고 한다.
◾ 성공 비결 & 실패 이유
- 성공 비결
긴 공부시간, 높은 집중력, 짧은 피드백 고리
- 실패 이유
삼천포로까지 빠지는 호기심, 고민을 하지 않음
◾ 좋았던 것, 부족했던 것, 개선할 것, 긍정 한마디
- 좋았던 것: 오랜시간 높은 집중력을 갖고 공부를 진행한 것, 방향성에 대한 많은 결정을 내린 것, 짧은 피드백 고리를 유지한 것.
- 부족했던 것: 전체적인 원인까지만 찾고 해결하지 못한 것, 여러 핑계를 대면서 공부를 중간중간 쉬게 된 것, 루틴을 완전히 복구하지 못한 것.
- 개선할 것: 예상결과 실제결과 파트를 어떻게 할지 고민해보기(다른 방식으로 변경? 또는 결과를 예상하는 방식을 변경? 등등), 루틴 되찾기 ㅠㅠ
- 긍정 한마디: 오늘은 공부를 재밌게 잘 즐겼다! 솔직히 좀 지루한 순간도 많았는데, 꿋꿋이 이어나가줘서 고마워! 오늘 하루도 수고했어~!
◾ 결론
- 예상 결과 실제 결과 파트 어떻게 할지 고민해보기
- 다른 방식으로 변경? 결과 예상방식 변경? 유지?
- 포스팅을 조금 공부한 내용만으로라도 매일 작성할 지, 적당히 공부한 것 같은 날만 작성할지 결정!
- 알고리즘 문제 꼭 풀기! 1순위!
- 건강과 루틴 되찾기
'Reflections > Daily' 카테고리의 다른 글
| 18일차 - 자바의신 21장, 제네릭, 컨텍스트 스위칭, HashMap, ConcurrentHashMap (1) | 2023.05.31 |
|---|---|
| 17일차 - 자바의신 20장, java.lang, System, 알고리즘 문제풀이, spring CRUD 게시판 요구사항 정의서 (0) | 2023.05.30 |
| 15일차 - 자바 16~17장, Nested class, Annotation, 배열 크기가 고정인 이유 (0) | 2023.05.23 |
| 14일차 - Git & Github 개념/사용법/규칙, 자바의 신 15장, String (0) | 2023.05.23 |
| 13일차 - 자바의신 14장 요약, 예외, throws, Throwable 클래스 (0) | 2023.05.16 |
당신이 좋아할만한 콘텐츠
소중한 공감 감사합니다