1. JVM 메모리 구조
1-1. 메모리 영역의 유형
- Heap 영역
- 일반적으로 실제값(객체-인스턴스-)을 저장하는 영역
- 변수에 할당된 실제 값은 Heap 영역에 저장된 값을 저장한다.
- 빈 칸으로는 존재할 수 없으며, 인스턴스 변수인 경우 기본값으로 초기화된다.
- 초기값이 없을 경우 초기화되는 값
- 숫자형: 0
- boolean형: false
- 참조 자료형: null
- Stack 영역
- 일반적으로 주소값을 저장하는 영역
- 기본 자료형의 경우, 값 자체가 Stack에 저장된다.
- 참조 자료형의 경우, Heap에 저장된 값의 시작 주소를 Stack에 저장한다.
- 지역 변수의 경우 초기값을 설정하지 않을 수 있다(변수에 값을 할당하지 않는 경우)
- 이 경우 해당 변수를 읽을 수 없다(사용할 수 없다).
- Method 영역
- class, static, final 영역 등 클래스 로더가 읽어들이는 다양한 정보가 저장되는 영역
- Java 8 이후 등 일부 영역에서는 '메타스페이스'라고 하기도 한다.
1-2. 예시 이미지

2. 자료형
2-1. 참조 자료형 - 배열
2-1-1. 정의
- 동일한 자료형을 묶어서 저장하는 자료형이다.
- 생성할 때 크기 지정을 해야하며, 한번 생성한 후에는 크기 변경을 할 수 없다.
- JavaScript 등과 가장 큰 차이점 중 하나이다.
2-1-2. 선언 방법
// 방법1 - 자료형[] 변수명;
int[] a;
String[] b;
// 방법2 - 자료형 변수명[];
int c[];
String d[];
2-1-3. 작동 흐름(값 없이 선언하는 경우)
- Stack에 참조 주소가 없는 상태로 배열 주소를 저장하는 값이 만들어진다.
- 값을 부여하면 실제값은 Heap에 저장된다.
- Stack은 Heap의 값이 저장된 주소를 저장한다(참조 주소 저장).
- 단, null이 부여된다면 주소에는 null이 저장된다.
- 예시)
int[] a = new int[3];
- int 배열 자료형을 선언 -> 참조 변수 할당 -> int 자료형 3개를 저장할 수 있는 공간 생성 -> 힙 메모리에 할당
2-2. 1차원 배열
2-2-1. 생성 및 값 대입하기(우변 기준)
- 방법 1
- 배열 객체를 생성하고 값을 대입
- int[] a = new int[3];
- 방법 2
- 배열 객체를 생성하는 동시에 값 대입하기
- int[] a = new int[] { 3, 4, 5 };
- 방법 3
- 대입할 값만 입력하기
- int[] a = { 3, 4, 5 };
2-2-2. 각 방법의 차이
- 방법 1과 2는 선언과 할당을 분리할 수 있다.
- 방법 3은 선언과 할당을 분리할 수 없다.
- 한번 선언된 배열의 변수를 이용해서 다른 변수에 값을 할당한다면, 각 변수의 변동은 상대 변수에 영향을 준다.
2-3. 배열 데이터 읽기
2-3-1. for 반복문 활용
- 배열의 크기만큼 루프를 수행하며 인덱스로 참조한다.
2-3-2. for-each 반복문 활용
3. 객체지향
3-1. 객체지향 요소
- 클래스
- 종류
- 실질적인 동작만 구현된다.
- 모든 동작이 구현되지 않은 클래스를 추상 클래스라고 한다.
- 인터페이스
- 명세만 존재하는 구조
- 서로 다른 하드웨어/소프트웨어 연결에 도움이 된다.
- 인터페이스와 추상 클래스를 통해 프로그램을 유연하게 만들 수 있다.
3-2. 상속
3-2-1. 정의
- 객체지향의 조건 중 하나
- 공통 속성을 미리 정의하고, 개별 인스턴스는 이를 상속, 필요한 요소를 추가한다.
3-2-2. 장점
- 코드 중복을 제거한다
- 다형적 표현이 가능하져서 다형성(객체를 여러 모양으로 표현)을 구현할 수 있다.
- 상속을 통해 만드러진 객체는 모두 같은 속성(타입)이므로, 관리가 편하다
3-2-3. 주의점
- Java 클래스는 다중 상속이 불가능하다.
- 상속 시 멤버(필드, 메서드, 이너 클래스)만 상속되고, 생성자는 상속되지 않는다.
- 자식 클래스 선언 시 사용 타입을 부모 클래스로 지정할 수 있지만, 이 경우 자식 클래스는 부모 클래스의 멤버만 사용할 수 있다.
3-2-4. 메모리 구조 관점에서의 상속
- 인스턴스 메서드 영역에 A클래스와 B 클래스가 존재한다.
- Stack 영역에서는 B객체(자식 클래스) 내부에 A객체(부모 클래스)가 존재한다.
3-3. 업캐스팅과 다운캐스팅
3-3-1. 필요한 이유
- 객체 선언 시 좌변과 우변의 데이터 타입은 동일해야 함
- 만약 일치하지 않는다면 형변환이 필요한데, 이를 클래스 간 관계에 적용한 것
3-3-2. 업캐스팅
- 자식 클래스에서 부모 클래스쪽으로 변환되는 것
- 명시적이지 않아도 컴파일러가 자동으로 수행한다.
- 부모 클래스가 자식 클래스를 포함할 수 있기 때문 -> 즉, 항상 가능하기 때문
- 업캐스팅 시, 자식 클래스의 인스턴스가 선언되더라도 해당 인스턴스의 메소드와 필드는 사용 불가능함
- 다운캐스팅을 해야 자식 클래스의 모든 정보를 사용할 수 있다.
3-3-3. 다운캐스팅
- 부모 클래스에서 자식 클래스쪽으로 변환되는 것
- 개발자가 명시적으로 수행해야 하는데 이는 다운캐스팅은 불가능할 수 있기 때문이다.
- instanceof 키워드로 가능 여부를 확인한다.
3-3-4. instanceof 키워드
- 캐스팅 가능 여부를 확인하기 위해 사용하는 키워드
- true로 반환될 시 캐스팅 가능하다.
3-3. 메서드 오버로딩과 오버라이딩
3-3-1. 메서드 오버로딩
3-3-1-1. 개념
- 동일한 이름을 가지되, 매개변수의 개수와 자료형이 서로 다른 메서드를 같은 공간에 정의하는 것
3-3-1-2. 주의점
- 원본 메서드와 매개 변수의 개수, 타입이 달라야 한다.
- 그 외의 메서드 구성 요소는 원본 메서드와 일치해야 한다.
3-3-2. 메서드 오버라이딩
3-3-2-1. 개념
- 부모 클래스에서 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것
- 부모 클래스의 메서드를 자식 클래스의 메서드로 덮어쓰는 개념이다.
3-3-2-2. 주의점
- 부모 클래스의 메서드와 시그니처와 리턴 타입이 동일해야 한다.
- 부모 클래스의 메서드보다 접근 지정자의 범위는 더 넓거나 동일해야 한다.
- 오버라이드 시 @Override를 메서드에 붙여야 한다.
- 메서드 오버라이딩은 부모 클래스의 값을 무의미하게 만들 여지가 있다.
-= 이를 해결하기 위해 추상 클래스를 활용한다.
3-3-2-3. 장점
- 부모 클래스 타입으로 자식 클래스 인스턴스 선언 시 다운캐스팅을 생략할 수 있다.
- 다형성을 구현해서 더 유연하게 클래스와 메서드를 관리할 수 있다.
참고 자료 및 출처