JVM의 구조와 자바의 실행방식을 설명해보세요
- 자바 컴파일러가 자바 소스코드를 읽어 바이트코드로 변환을 시킵니다.
- 그 후 클래스 로더를 통해 클래스 파일들을 jvm으로 로딩합니다.
- 로딩된 클래스 파일들은 실행엔진을 통해 해석되며
- 해석된 바이트코드는 런 타임 데이터 영역에 배치되어 실직적인 동작이 이루어집니다.
GC가 무엇이고 왜 필요하며 동작 방식을 설명해보세요.
GC는 가비지 컬렉터의 약자로 JVM의 힙 영역에서 사용하지 않는 객체를 삭제하는 프로세스를 의미합니다. 즉 자동으로 메모리를 관리해주는 작업의 총칭이며, 메모리 누수를 막아 안정적인 프로그래밍이 가능하도록 합니다.
씨언어와 같은 오래된 언어에서는 개발자가 직접 메모리를 관리해야 하지만 자바와 같이 새로운 언어들은 가비지 컬렉터를 도입했고, 이렇게 자동으로 메모리를 관리하는 언어를 매니지드 언어라고 합니다.
GC 루트에서부터 각각 참조하고 있는 객체들을 하나씩 탐색해 나갑니다. 이때 참조되지 않는 객체는 언써쳐블하다고 표현되며 가비지 컬렉트의 대상이 됩니다.
가비지 컬렉트는 마크앤 스윕 알고리즘을 이용하여 동작하게 됩니다. 마크는 GC Root로부터 모든 변수를 스캔하면서 각각 어떤 객체를 참조하고 있는지 알아서 마킹합니다.
즉 reachalbe한 객체와 unreachalble한 객체를 식별하는 과정이라고 할 수 있습니다.
그 다음 스왑 과정은 unreachable한 객체를 힙영역에서 삭제하는 과정입니다.
필요한 것들만 마킹한 다음 마크가 되지 않는 것들은 버리는 방식입니다.
힙의 구조는
영 영역과 올드 영역이 존재합니다.
영 영역은 새로운 객체들이 할당되는 곳이며
올드 영역은 영 영역에서 살아남은 객체들이 존재하는 영역입니다.
그 기준은 age 비트값이 있기 때문에 특정 age가 도달하면 올드 영역으로 옮겨지게 됩니다.
영 영역은 또한 에덴, 서바이벌0,1으로 나뉘어집니다.
새로운 객체가 에덴 영역에 할당되고 더이상 할당될 곳이 없다면 마이너 GC가 발생합니다.
마이너 GC가 발생하면 마크앤 스윕 과정이 일어납니다.
그리고 남은 객체는 위에 말씀드린 것처럼 age 값이 증가합니다.
컬렉션 프레임워크에 대해서 설명해주세요
자바 컬렉션에는 List, Map, Set 인터페이스를 기준으로 여러 구현체가 존재합니다.
이에 더해 Stack, Queue 인터페이스도 존재합니다. 왜 이러한 컬렉션을 사용할까요?
그 이유는 다수의 데이터를 다루는데 표준화된 클래스들을 제공해주기 때문에 자료구조를 직접 구현하지 않고 편하게 사용할 수 있기 때문입니다.
또한 배열과 다르게 객체를 보관하기 위한 공간을 미리 정하지 않아도 되기 때문에 상황에 따라 객체의 수를 동적으로 정할 수 있다는 장점도 있습니다. 이러한 장점은 프로그램의 공간적인 효율성 또한 높여줍니다.
List
- 리스트 인터페이스를 직접 오버라이드를 통해 사용자가 정의하여 사용할 수도 있으며 대표적인 구현체로는 ArrayList가 존재합니다. 이는 기존에 있었던 Vector를 개선한 것이며 이외에도 LinkedList도 존재합니다.
Map
- 대표적인 구현체로 HashMap이 존재합니다. 키-벨류의 구조로 이루어져 있으며 맵에 대한 구체적인 내용은 자료구조 부분의 해쉬테이블과 일치합니다.
- 키를 기준으로 중복된 값을 저장하지 않으며 순서를 보장하지 않습니다. 키에 대한 순서를 보장하기 위해서는 LinkedHashMap을 사용합니다.
Set
- 대표적인 구현체로 HashSet이 존재합니다 value에 대해서 중복된 값을 저장하지 않습니다. 사실 set 자료구조는 map의 key-value 구조에서 key 대신 value가 들어가 value를 key로 하는 자료구조일 뿐입니다.
- 마찬가지로 순서를 보장하지 않으며 순서를 보장해주기 위해서는 LinkedHashSet을 사용합니다.
Stack & Queue
- 스택은 직접 new 키워드로 사용할 수 있으며 Queue인터페이스는 JDK1.5부터 Linked에 new 키워드를 적용하여 사용할 수 있습니다.
제네릭에 대해서 설명해주세요
클래스 타입을 파라미터로 만든 것 입니다. jdk1.5부터 추가되었으며 <TYPE> 문법을 이용합니다.
이는 컴파일 타임에 구체적인 타입이 결정되도록 함으로써 런타입 예외를 예방할 수 있습니다.
또 객체를 꺼낼 시 형변환을 통한 타입을 맞출 필요가 없어 코드를 간결하게 줄일 수 있다는 장점이 있습니다
애노테이션에 대해 설명해주세요.
애노테이션이란 본래 주석이란 뜻을 가지고 있습니다. 인터페이스를 기반으로 한 문법인데요
주석과는 그 역할은 다르겠지만 주석처럼 코드에 달아 클래스에 특별한 의미를 부여하거나 기능을 주입할 수 있어요.
또 해석되는 시점을 정할 수 있습니다.(Retention Policy)
애노테이션에는 크게 세가지 종류가 있는데요 JDK에 내장되어 있는 Built-in 애노테이션과 애노테이션에 대한 정보를 나타내기 위한 애노테이션인 Meta Annotation, 그리고 개발자가 직접 만들어내는 Custom Annotation이 있습니다.
빌트인 애노테이션은 상속받아서 메서드 오버라이드할 때 나타나는 @Override 애노테이션이 대표적인 예입니다.
오버라이딩과 오버로딩이 무엇이며 어떤 차이가 있을까요?
오버라이딩은 상위 클래스의 메서드를 재정의 하는 것을 의미합니다. 또한 런타임 다형성 이기도 합니다.
오버로딩은 같은 클래스 내에서 동일한 메서드 이름을 가지지만 매개변수의 타입, 개수를 다르게 구현할 수 있다는 것을 의미하며 컴파일 타임 다형성이기도 합니다. 따라서 오버라이딩이 될 수 있습니다.
추가로 Override 애노테이션을 꼭 써야하는 이유는 무엇일까요?
- 이 애노테이션은 컴파일 타임에 오버라이딩에 대한 안정성을 부여해주기 때문에 써주는 것이 좋습니다.
인터페이스와 추상클래스의 차이점을 설명해보세요.
둘의 큰 차이점은 사용 용도에 있습니다. 관계를 설명한다면
추상클래스는 IS - A 즉 ~이다 라고 설명할 수 있다면,
인터페이스는 Has - A ~을 할 수 있는 이라고 설명을 할 수 있습니다.
이렇게 구분되는 이유는 다중상속 여부에 따라 용도를 정한 것이며 자바의 특성상으로 한개의 클래스만 상속이 가능하여 해당 클래스의 구분은 추상클래스를 통해 해결하고 할 수 있는 기능들은 인터페이스로 구현할 수 있습니다.
두번째 차이점은 접근자가 있습니다.
인터페이스에서 모든 변수는 public static final만 가능하고 메서드는 public abstract만 가능합니다.
추상 클래스는 static이나 final이 아닌 필드를 가질 수 있고 public, protected, private모두 가질 수 있습니다.
세번째로 사용 의도입니다.
추상 클래스는 상속할 객체들의 공통점을 찾아 추상화 시켜 놓은 것입니다.
인터페이스는 상속관계를 타고 올라갔을 때 다른 조상 클래스를 상속하더라도 같은 기능이 필요한 경우 사용할 수 있습니다.
클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용합니다.
클래스는 무엇이고 객체는 무엇인가요?
- 클래스는 객체를 정의하는 설계도와 같은 의미로 사용됩니다.
- 객체는 식별 가능한 개체 또는 사물이며 객체의 상태(속성, 특성)를 멤버 변수, 객체의 행동(기능)을 메서드 혹은 멤버 함수라고 표현합니다.
- 객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가집니다.
- 인스턴스(클래스가 메모리에 생성된 상태) 들을 통칭하는 용도로 사용합니다.
자바 static이란 무엇인가요?
static은 클래스 멤버라고 하며, 클래스 로더가 클래스를 로딩해서 메서드 메모리 영역에 적재할 때 클래스 별로 관리됩니다.
static 키워드를 통해 생성된 정적 멤버들은 PemGen 또는 Metaspace에 저장되며 저장된 메모리는 모든 객체가 공유하며 하나의 멤버를 ㄹ어디서든지 참조할 수 있는 장점이 있습니다.
그러나 GC의 관리 영역 밖에 존재하기 때문에 프로그램 종료 시 까지 메모리가 할당된 채로 유지하게 됩니다. 너무 남발하게 되면 시스템에 약영향을 미칠 수 있기에 충분히 고려하여 사용해야 합니다.
자바의 원시타입들은 무엇이 있으며 각각 몇바이트를 차지하나요?
프리미티브타입으로
byte - 1byte
short - 2byte
int - 4byte
long - 8byte
float - (실수형) 4byte
double - (실수형) 8byte
char - 2byte (유니코드 문자데이터)
boolean - 1byte
접근제어자의 종류와 이에대해 설명해주세요
public - 모든 곳에서 사용 가능
protected - 해당 패키지 내, 클래스 상속받은 곳 사용가능
default - 해당 패키지에서만 접근 가능
private - 클래스 내에서만 사용
객체지향에 대해서 설명해주세요
객체지향 프로그래밍이란 프로그램을 설계하는 개념이자 방법론 중 하나입니다. 주변에 존재하는 모든 사물, 생명체 하나하나를 객체로 볼 수 있습니다.
즉 객체지향이란 프로그램을 상태와 행위로 이루어진 객체라는 기본 단위로 나누어 이 객체들간의 상호작용을 통해 프로그램을 설계하고 개발하는 것입니다.
객체지향의 중요한 특징 4가지로
캡슐화
- 데이터와 데이터를 처리하는 함수를 하나로 묶는 것
정보은닉
- 다른 객체에게 자신의 정보를 숨기고 자신의 연산만을 통해 접근을 허용하는 것
추상화
- 여러 객체들의 공통적인 특징을 도출해 내는 것
상속
- 이미 정의된 상위 클래스의 모든 속성과 연산을 하위 클래스가 물려받는 것
다형성
- 하나의 변수 또는 함수가 상황에 따라 다른 의미로 응답하는 것
SOLID에 대해서 설명해주세요.
네 SOLID는 다섯가지 규칙의 첫글자를 따온 것인데요 가장먼저
Single Responsibillity Principle(단일책임원칙)이 있습니다.
단일책임원칙은 클래스는 오직 하나에 대해서만 책임을 가져야 한다는 뜻을 가지구 있는데요
만약 클래스가 여러 작업을 책임져야한다면 버그 발생 가능성을 높이며 많은 기능 중 한가지를 변경할 때 모르는 사이에 다른 기능에 영향을 줄 수 있습니다.
따라서 단일책임 원칙의 목적은 행동을 분리하는 것입니다.
두번째로 개방-폐쇄 원칙인데요. 이것은 클래스 확장에는 개방적이고 수정에는 폐쇄적이어야 한다는 뜻을 가지구 있습니다.
클래스의 현재 코드를 변경하는 것은 해당 클래스를 사용하고 있는 모든 곳에 영향을 주게 되는데요 만약 클래스에 더 많은 기능을 부여하고 싶다면 이상적인 방법으로 변경이 아니라 확장을 해야합니다.
따라서 개방폐쇄원칙의 목적은 기능의 변경없이 해당 클래스의 기능을 확장하는것이 목적입니다. 저는 자바개발자이기 때문에 대표적으로 인터페이스를 적극적으로 활용해야한다는 것을 느낄 수 있었어요.
세번째로 Liskov Substitutiong Principle(리스코프 치환원칙)이 있습니다.
이 원칙은 만약 S가 T의 서브타입이라면, T는 어떠한 경고도 내지 않으면서 S로 대체가 가능해야 합니다.
자식클래스가 부모클래스의 기능을 똑같이 수행할 수 없을 때, 이는 버그를 발생시키는 요인이 됩니다.
자식 클래스는 부모클래스처럼 똑같은 요청에 대해 똑같은 응답을 할 수 있어야 하고, 응답의 타입 또한 같아야 한다는 원칙입니다.
네번째로 Interface Segregation Principle(인터페이스 분리 원칙)입니다.
클라이언트는 사용하지 않는 메서드에 대해 의존적이지 않아야 한다는 원칙입니다.
클래스가 서로 관계없는 기능들을 가지고 있다면 낭비가 되고, 예상치 못한 버그를 발생시킬 수 있습니다.
ISP의 목적은 액션 집합을 더 작은 액션 집합으로 쪼개어 클래스가 필요한 액션들만 실행할 수 있도록 하는것입니다.
다섯번째 의존성 역전 원칙 Dependency Inversion입니다.
추상은 구체에 의존하지 않아야 하며 구체는 추상에 의존해야 합니다.
고수준의 모듈은 저수준 모듈에 의존적이면 안되고 둘다 추상에 의존적이어야 한다는 원칙이에요.
여기서 고수준 모듈은 도구와 함께 동작하는 클래스를 뜻하며 저수준은 수행하기 위한 도구를 뜻합니다.
DIP의 목적은 인터페이스를 통해 고수준 클래스에 저수준 클래스에 대해 의존성 가지는 것을 줄이는 것입니다.
동일성과 동등성을 설명해주세요
동일성은 인스턴스가 실제로 같은 인스턴스임을 의미하는 바로 == 연산자를 통해 비교합니다.
동등성은 서로 다른 인스턴스이지만 가지고 있는 값이 같음을 의미하며 equals 메서드로 비교합니다.
자바에서 equals를 따로 오버라이드 하지 않으면 상위 클래스인 Object 클래스의 equals 메서드가 호출되게 되는데요 Object 안에서는 == 을 비교하고 있어요 따라서 동등성을 비교하기 위해선 재정의를 해주어야 합니다.
원시타입과 참조타입의 차이는 뭐에요?
둘의 차이는 먼저 저장되는 영역이 다른다는 부분이 있을 것 같아요
원시타입은 스택영역에 저장되며 참조타입은 스택영역에 참조 값만 있고 데이터는 힙 영역에 저장됩니다.
즉 참조타입은 최소 2번 메모리 접근을 해야하고 일부 타입의 경우 값을 필요로 할때 언박싱 과정을 거쳐야 하므로 원시타입에 비교한다면 접근 속도는 느린 편이라고 말할 수 있습니다.
또 메모리 관점에서 본다면 참조타입이 원시타입보다 메모리 양이 높습니다.
null관점으로 원시타입은 null을 담을 수 없지만 참조타입은 담을 수 있습니다. 이 이유는 원시타입은 각 디폴트 값이 있기 때문입니다.
String / StringBuffer / StringBuilder 차이가 뭐에요?
Java 에서 String은 불변성을 가지는 특성이 있습니다. 즉 변하지 않는 문자열을 자주 사용하는 경우에는 String을 사용하는 것이 좋습니다.
응집도와 결합도
결합도란 어떤 기능을 실행하는데 다른 클래스나 모듈들이 얼마나 서로 연관되어있는지 의존적인지를 나타냅니다. 결합도가 높으면 서로가 강하게 연결되어 있기 때문에 수정이 일어날 경우 유지보수하기 어렵다는 단점이 있습니다. 따라서 저희는 결합도를 적절하게 낮춰서 설계를 해야하는데 그러기 위해서는 응집도를 높여야합니다. 응집도는 클래스나 모듈안의 그 요소들이 얼마나 밀접하게 관련되어 있는지를 나타냅니다. 이러한 응집도는 높을수록 기능들이 흩어져있지 않고 자기 자신을 직접 책임을 지도록 하고 있기 때문에 코드를 수정하기 쉬워지는 장점이 있습니다. 정리해보면 저희는 결합도를 낮추도록 코드를 작성해야 하며 그러려면 응집도를 강하게 작성해야 합니다.
추상화란 무엇인가요?
추상화란
추상클래스와 인터페이스의 차이는 무엇일까요?
차이점은
다형성이란 뭔가요?
ㅇㅇㅇ