요즘 Java 부터 DB, 자료구조 등등 이론 공부를 하다가
실제로 어떤 하나의 개념을 누군가 물어봤을때 설명해주기에는 너무 모호하게 알고 있다는걸 깨달았다.
집을 지어야 하는데 기본 지식이 없이 무작정 재료만 주워 모아 집 짓듯이 코딩하는 느낌,,
특히 이렇게는 항상 사용하는 것들도 막상 면접자리에서는 대답도 못하겠구나 하는 생각에
이렇게 자바부터 정리를 해보려 한다!
정리에 있어 첫 번째는 가장 기본이 되는 Java 관련된 기본적인것들을 선택해 보았다.
💡 Java의 특징을 설명해주세요.
- 객체지향 프로그래밍 언어
- 기본 자료형을 제외한 모든 요소들이 객체로 표현됨
- 객체 지향의 특징인 "캡슐화, 다형성, 상속"이 잘 적용된 언어
- JVM(Java Virtual Machine:자바가상머신) 위에서 동작하므로 운영체제에 독립적임 → JVM만 설치하면 컴퓨터 운영체제와는 관계 없이 작동함 → 단, JVM 위에서 동작하므로 실행 속도가 상대적으로 느림
- GC(Garbage Collector)를 이용한 자동적 메모리 관리가 가능
- 다중 상속, 타입에 엄격하고 제약도 많음
💡 OOP(객체지향 프로그래밍)에 대해 설명해주세요.
- 컴퓨터 프로그래밍 방식 중 하나
- 프로그래밍에 필요한 데이터의 추상화를 통해 객체를 만들고, 각 객체들간의 유기적 상호작용을 통해 로직을 구성하는 프로그래밍 기법
- Pros
- 코드 재사용성 (상속을 통해 프로그래밍 하게 되면 코드 재사용률을 높일 수 있음)
- 유지보수가 용이 (객체 지향 프로그래밍에서는 수정할 변수/메서드 등 일부만 수정하면 됨)
- 개발속도 향상
- 직관적인 코드 분석 가능
- Cons
- 실행 속도가 느림
- 프로그램 용량이 큼
- 설계에 많은 시간이 소요됨 (클래스별, 객체별로 설계가 필요하고 상속 등의 구조에 대한 설계도 필요하므로)
💡 OOP의 4가지 원칙, 특징에 대해 설명해주세요.
👉 캡슐화
변수와 메서드를 하나의 덩어리로 묶어, 데이터를 외부에서 직접 접근하는 것이 아닌 함수를 통해서만! 접근하는것을 의미
→ 실제 구현 부분을 외부에 드러내지 않는 접근제어자/인터페이스
→ 정보 은닉
👉 상속
이미 정의된 클래스의 모든 속성과 연산을 하위 클래스가 물려받는 것
👉 추상화
인터페이스로 클래스들의 공통적인 특성들을 묶어서 표현하는 것
👉 다형성
하나의 참조 변수로 여러 타입의 객체를 참조할 수 있는 것
💡 Java의 컴파일 과정을 설명해주세요.
- 자바 소스 코드 작성
- 해당 소스 파일을 자바 컴파일러가 컴파일함
- 컴파일된 바이트 코드를 JVM의 클래스 로더에게 전달
- 클래스로더가 동적 로딩을 통해 필요한 클래스들을 로딩 및 링크해서
→ 런타임 데이터 영역인 JVM 메모리에 올림 - 실행 엔진이 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행
💡 Java의 메모리 영역에 대해 설명해주세요.
자바의 메모리 영역은 크게 "Method, Stack, Heap" 영역으로 구분되며, 데이터 타입에 따라 할당된다.
👉 메소드(Method) 영역
- 메모리 영역 할당 시점 : JVM이 동작해서 클래스가 로딩될 때 할당
- 전역변수, static 변수를 저장하며 이 영역은 프로그램의 시작~종료까지 메모리에 남아있게 됨
👉 스택(Stack) 영역
- 메모리 영역 할당 시점 : 컴파일 타임에 할당
- 지역변수, 매개변수 데이터 값이 저장되는 공간
→ primitive 타입의 데이터(int, long, boolean, double, byte 등) - 메소드가 호출될 때 스택 메모리에 할당되고, 종료되면 메모리에서 사라짐
- LIFO(Last In First Out) 구조
→ 후입선출! (scope 의 범위를 벗어나면 스택 메모리에서 사라짐)
👉 힙(Heap) 영역
- 메모리 영역 할당 시점 : 런타임시 할당
- JVM이 관리하는 프로그램 상에서, 데이터를 저장하기 위해 런타임 시 동적으로 할당해 사용하는 영역
- 참조형(Reference Type) 데이터 타입을 갖는 객체(인스턴스), 배열 등이 저장됨
→ (new 키워드로 생성되는 객체(인스턴스), 배열 등) - Heap 영역은 Stack 영역과는 다르게 보관되는 메모리가 호출이 끝난 뒤에도 삭제되지 않고 유지됨!
→ 그러다 어떠한 참조 변수도 Heap 영역의 인스턴스를 참조하지 않게 되면 GC에 의해 메모리에서 청소됨 - Stack은 스레드 갯수마다 각각 생성되지만, Heap은 몇개의 스레드가 존재하더라도 단 하나의 Heap 영역만 존재함
- 단, Heap 영역의 오브젝트들을 가리키는 레퍼런스 변수는 Stack에 적재됨
💬 Stack/Heap 관련 참고 블로그
https://inpa.tistory.com/entry/JAVA-☕-그림으로-보는-자바-코드의-메모리-영역스택-힙https://yaboong.github.io/java/2018/05/26/java-memory-management/
💡 JVM의 역할에 대해 설명해주세요.
- JVM은 스택(Stack) 기반으로 동작하며, 자바 바이트 코드를 OS에 맞게 해석하는 역할을 함
- 또한 GC를 통해 자동적인 메모리 관리를 해줌
💡 가비지 컬렉션 (GC : Garbage Collection)에 대해 설명해주세요.
- JVM의 메모리 관리 기법 중 하나
- 시스템에 동적 할당되었던 메모리 영역 중 필요 없어진 메모리 영역을 회수해서 메모리를 관리해주는 기법
아래는 조금 더 실무 코드에서 사용되는것과 가시적으로 밀접한 키워드에 대한 질문들이라고 생각되어 구분해봤다.
💡 자바의 접근 제한자(Access Modifier)에 대해 설명해주세요.
4가지로, 변수 또는 메소드의 접근 범위를 설정해주기 위해 사용하는 Java 예약어.
- public → 접근 제한이 없음. 해당 프로젝트 내 어디서든 사용 가능
- protected → 해당 패키지 내에서, 그리고 타 패키지에서 상속받아 child class에서도 접근 가능
- private → 해당 클래스 내에서만 접근 가능
- (default) → 해당 패키지 내에서만 접근 가능
💡 static은 무엇인가요?
- static(정적) 키워드를 사용해 static 변수, static 메소드를 만들 수 있음
→ 이 둘을 합쳐 정적 멤버라고 한다. - static 키워드를 사용한 변수/메소드는 클래스가 메모리에 올라갈 때 자동으로 생성되며,
클래스 로딩이 끝나면 바로 사용 가능함
→ 즉, 인스턴스(객체) 생성 없이 바로 사용이 가능하다! - 특징으로는, 모든 객체가 메모리를 공유한다는 것.
또 GC의 관리 영역 밖에 있어 프로그램 종료 시까지 메모리 값이 유지된 채로 존재한다는 것.
static 요약! 👉 static 키워드를 통해 생성되는 정적 멤버들은 Heap 영역이 아닌 Static 영역에 할당됨.
이 static 영역에 할당되는 메모리는 모든 객체가 공유하기 때문에, 하나의 정적 멤버를 어디서든 참조할 수 있다는 장점이 있음. 하지만 GC 관리 영역 밖에 존재하므로 프로그램 종료시까지 메모리에 값이 유지된 채로 존재하게됨.
따라서 static을 남발하면 성능에 악영향을 줄 수 있음.
💡 static을 사용하는 이유는 무엇인가요?
- 인스턴스(객체) 생성 없이 바로 사용 가능하므로,
프로그램 내에서 공통으로 사용되는 데이터들을 관리할 때 사용하면 좋음
(자주 변하지 않는 값, 공통으로 사용되는 값 같은 공용 자원에 대한 접근에 있어서 접근시마다 메모리에 로딩하거나 값을 읽어들이는 것이 아닌 일종의 전역변수같은 개념을 통해 접근하므로 비용은 줄이고 효율은 높일 수 있음)
💬 static 관련 참고 블로그
https://dev-coco.tistory.com/23
💡 Overloading 과 Overriding 의 차이점은 무엇인가요?
👉 Overloading
- 동일한 이름의 메소드를 여러개 정의하는 것
- 메소드명은 같고, 매개변수의 타입 또는 갯수가 달라야함!
- (return type과 접근 제어자는 영향 x)
- using reason? → 메소드명 절약 가능, 동일 기능의 메소드를 하나의 이름으로 사용 가능
👉 Overriding
- 상위 클래스의 메소드를 하위 클래스에서 재정의 (상속에서 나오는 개념!)
- 상속받은 메소드를 그대로 사용해도 되지만, 필요에 따라 변경해야 하는 경우 오버라이딩 사용
- 재정의 하는 것이므로 메소드명, 매개변수, 리턴 타입 등 모두 같아야함!
👉 차이점 한줄 정의! → 오버로딩은 같은 클래스 내에서, 오버라이딩은 상속관계에서!
💡 final이란 무엇이며 언제 사용하나요?
(+ final / finally / finalize 의 차이를 설명해주세요.)
- final 은 클래스/메소드/변수/인자를 선언할 때 메모리에 1회만 할당하고 싶은 경우 사용함
- final 변수는 한 번 초기화되면 그 이후 변경 불가능
- final 메소드는 다른 클래스가 이 클래스를 상속할 때 이 메소드의 오버라이딩을 금지함
- final 클래스는 다른 클래스에서 이 클래스를 상속할 수 없음
- finally 는 try-catch 와 함께 사용! try-catch 가 종료될 때 finally 블럭이 항상 수행됨
(마무리 해줘야 하는 작업이 존재하는 경우 해당 코드를 작성해주는 코드 블록이라고 보면됨) - finalize 는 Object 클래스에 정의되어 있는 메소드로,
GC에 의해 호출되는 메소드에 호출하면 절대 안되는 메소드..!
→ 그 이유는 GC가 발생하는 시점이 불분명하기 때문에 해당 메소드가 실행된다는 보장이 없고, finalize() 메소드가 오버라이딩 되어 있으면, GC가 이루어질 때 바로 Garbage Collecting이 되지 않음,, GC가 지연되면서 OOME(Out of Memory Exception)이 발생할 수 있기 때문에 finalize() 메소드를 오버라이딩해 구현하는걸 권장하지 않는다고 함)
final 변수 : 상수라고도 불리며, 선언 동시에 초기화 이후 수정 불가. get만 가능.
final 메소드 : 오버라이딩 불가능. 상속 받은 그대로 사용해야함.
final 클래스 : 상속 불가, subclass 불가.
💡 싱글톤 패턴은 무엇인가요?
전역 변수를 사용하지 않고 클래스의 인스턴스(객체)를 하나만 생성하도록 해서,
생성된 객체를 어디서든 참조 가능하게 하는 패턴
- 다양한 곳에서 인스턴스 선언을 새로 하지 않아도 되므로, 메모리 낭비를 줄일 수 있음
- 인스턴스 정보가 변경되더라도 결국 한개의 인스턴스를 사용하므로 동기화 관련 문제가 없음
- 인스턴스의 상태가 모두 동일하므로, 어디서 사용하더라도 같은 결과를 확인할 수 있음
- 하지만! 객체간 결합이 강해진다는 문제가 발생함
→ 이러한 문제를 해결해주는 의존성 주입(DI : Dependency Injection)
결론적으로, 싱글톤을 사용하는 이유는, 인스턴스 재사용을 위해서 라고 생각하면 된다.
'for technical interview' 카테고리의 다른 글
개발자 기술면접(Java) : Java(2) (0) | 2023.06.01 |
---|
댓글