-
[기술면접] 신입 개발자 JAVA 예상 면접 질문취업준비/기술면접 2022. 9. 19. 18:30
● 자바 장점
- 자바 가상머신 JVM(Java Virtual Machine)만 설치하면 컴퓨터의 운영체제와 상관없이 작동함으로 os에 독립적이다.
- 가비지 컬렉터를 통해 메모리 관리가 가능하다.
- 멀티 스레드 프로그래밍을 지원해 한 개의 프로세스 내부에서 여러 개의 일을 동시에 처리할 수 있으며 동적 로딩을 지원한다. apache, spring 등 자바를 지원하는 수많은 오픈 소스 프로젝트가 있다.
● 자바 가상머신 JVM이란?
: 자바 프로그램 실행환경을 만들어주는 소프트웨어이다. Java는 어떠한 플랫폼에 영향을 받지 않는다. JVM을 사용하면 하나의 바이트코드(.class)로 모든 플랫폼에서 동작하도록 할 수 있다.
● JVM 실행 과정
1. 자바 컴파일러(javac)가 자바 소스 코드(.java)를 컴파일 하면 바이트 코드(.class)가 생성된다. 바이트코드는 JVM에서 읽을 수 있는 코드이다.
2. 바이트 코드를 Class Loader를 통해 JVM Runtime Data Area에 올린다. 즉) 메모리에 데이터를 저장/로딩한다.
3. Runtime Data Area에 로딩 된 .class들은 Excution Engine을 통해 해석된다. 해석된 바이트 코드는 각 메모리 영역에 배치되어 수행하며 이 과정에서 GC 과정과 스레드 동기화가 이루어진다.● 클래스 로더란?
: 자바는 런타임에 클래스 로드하고 링크하는 특징이 있다. 클래스 로더는 런타임 중에 JVM의 Method 영역에 동적으로 Java 클래스를 로드하는 역할을 한다.
●객체지향이란?
: OOP(Object-Oriented-Programing) 순차적으로 프로그램이 동작하는 기존의 것들과 다르게 객체와 객체의 상호작용을 통해 프로그램이 동작하는 것이다. 객체란 현실세계의 사물을 의미하고 그 사이의 관계, 상호 작용을 프로그램이 나타낸다.객체지향의 장점으로 하나의 클래스를 바탕으로 서로 다른 상태의 인스턴스를 만들며 다른 행동을 할 수 있다. 이로 인해 코드의 재사용성이 높고 변경이 용이하다.
객체지향 프로그래밍의 특징은 다음과 같다.
1. 추상화 : 실제를 객체화하는 게 아닌 필요한 정보만을 중심으로 간소화하는 것. 객체 간 공통적인 속성과 기능을 중심으로 추상화한다.
2. 캡슐화 : 추상화를 통해 객체를 정의했다면, 객체에 필요한 데이터나 기능(메서드)을 책임있는 객체에 그룹화 시켜주는 것을 캡슐화라고 한다. 또한 캡슐화는 메서드 안에서 어떠한 일이 일어나고 있는지 모르게 해야한다. ex) 메서드 명에 변수 이름을 노출시키지 않는다.
3. 상속성 : 상위 클래스의 기능을 하위 클래스가 사용할 수 있는 개념. 중복되는 코드의 재사용성을 위함.
4. 다형성 : 자바에서 다형성은 상속(오버라이딩)과 인터페이스를 통해 이루어진다. 하나의 객체를 다양한 타입으로 사용할 수 있게 한다. 코드의 재사용성, 개발자의 편의성, 유지보수의 편리함. 예를들어 키보드에서 esc와 enter는 누른다라는 같은 동작을 통해 실행되지만 취소, 입력이라는 다른 실행 목적을 가진다.● 객체지향 5가지 원칙
1. 단일 책임 원칙 (Single Responsibility Principle, SRP)
: 하나의 클래스는 하나의 책임만 가져야 한다. 변경사항이 있을 때, 애플리케이션의 파급효과가 적으면 SRP 원칙을 잘 따른 것으로 볼 수 있다.
2. 개방 폐쇄 원칙 ( Open Closed Principle , OCP)
: 높은 응집도와 낮은 결합도라는 원리로 볼 수 있다.
- 응집도란? 모듈 내부 요소들이 서로 관련되어 있는 정도이다. 응집도가 높다는 건 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 뜻이며, 기능적으로 모여있다는 것이다.
- 결합도란? 모듈 간에 상호 의존하는 정도를 의미한다. 결합도가 낮다는 것은 책임과 관심사가 다른 객체 또는 모듈과 낮은 결합도를 유지해야한다. 즉) 하나의 변경이 발생할 대 다른 모듈과 객체로 변경에 대한 요구가 전파되지 않는 상태를 말한다.
3. 리스코프 치환 원칙 ( Liskov Substitution Principle, LSP)
: 객체는 프로그램의 정확성을 깨지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 다형성을 지원하기 위한 원칙으로 하위 클래스는 인터페이스 규약을 지켜 작성되어야 한다.
4. 인터페이스 분리 원칙 (Interface Segragation Principle, ISP)
: 범용 인터페이스는 하나보다는 특정 클라이언트를 위한 여러 개의 인터페이스 분리가 더 좋다.
5. 의존 관계 역전 원칙 (Dependency Inversion Principle , DIP)
: 프로그래머는 구체화가 아니라 추상화에 의존해야 한다. 구현 클래스(구현체)가 아니라 인터페이스(역할)에 의존하르는 이야기이다. 예를 들어 배역(인터페이스)과 배우(구현체)를 예로 들 수 있다. 연극은 특정 배우를 염두해두고 기획되기 보다 배역에 집중해서 기획되어야 한다.
● 클래스와 객체
: 클래스란 '객체를 정의해 놓은 것.혹은 객체의 설계도 또는 틀' 이라고 정의할 수 있다. 객체의 사전적인 정의는 '실제로 존재하는 것'이다. 우리가 주변에서 볼 수 있는 책상, 의자와 같은 사물이 곧 객체이다. 예를 들어보자면, TV 설계도(클래스)는 TV라는 제품(객체)를 정의한 것이며, TV(객체)를 만드는데 사용된다. 클래스는 단지 객체를 생성하는데 사용될 뿐, 객체 그 자체는 아니다. 하나의 설계도만 잘 만들어 놓으면 제품을 만드는 일이 쉬워지기 때문에 클래스를 먼저 정의한 다음 클래스를 통해 객체를 생성한다.
●객체와 인스턴스
: 클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스라고 한다. 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있으며, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 보다 강조하는 의미를 가지고 있다. 예를 들면 '책상은 인스턴스다'라고 하기 보다는 '책상은 객체다' 라는 쪽이, '책상은 책상 클래스의 객체이다'라고 하기 보단 '책상은 책상 클래스의 인스턴스다'라고 하는 것이 더 자연스럽다.
● 데이터 타입 종류
- 기본형(primary type) : boolean, char, byte, short, int, long, float, double, 계산 기가능. 변수 값 자체를 저장.
- 참조형(reference type) 변수 : 기본형을 제외한 나머지 타입. String, Array, 개인이 정의한 클래스. 메모리상에 객체가 있는 위치 저장
●접근제어자(Acess Modifier)
: 변수 또는 메서드의 접근 범위를 설정해주기 위해 사용하는 자바의 예약어
- public : 어떤 클래스에서도 접근 가능.
- protected : 같은 패키지, 해당 클래스를 상속 받은 외부 패키지의 클래스에서 접근 가능.
- default : 같은 패키지에서만 접근 가능.
- private : 해당 클래스에서만 접근 가능.
● hashCode와 equals
: 객체를 식별하는 하나의 정수값을 말한다. Object의 hashCode() 메서드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체 마다 다른 값을 가지고 있다. 객체의 값을 동등성 비교시 hashCode()를 오버라이딩할 필요가 있다. hashCode()는 메서드를 실행해서 리턴된 해시코드 값이 같은지를 본다. 해시 코드 값이 다르면 다른 객체로 판단하고 해시 코드 값이 같으면 eauqls() 메서드로 다시 비교한다. 이 두개가 모두 맞아야 동등 객체로 판단한다.
HashTable은 <key, value> 형태로 데이터를 저장하는데, 이때 해시함수를 이용해 key 값을 기준으로 고유한 식별값인 해시값을 만든다. 하지만 hashTable 크기는 한정적이기 때문에 서로 다른 객체라도 같은 해시값을 갖게될 수 있다. 이것을 해시충돌이라고 한다. 이처럼 해시값의 버킷안에 다른 객체가 있는 경우 equals 메서드가 사용된다.
따라서 equals()와 hashcode()를 같이 재정의해야한다.
●Wrapper 클래스
: 기본 자료형을 객체로 표현해야 할 때 사용하는 클래스 표현.
프로그램에 따라 기본 데이터를 객체로 취급해야 하는 경우가 있다. 예를 들어, 메서드의 인수로 객체 타입만이 요구되면, 기본 타입의 데이터를 그대로 사용할 수 없다. 이때 기본 타입 데이터를 먼저 객체로 변환한 후 작업을 수행해야 한다. 이렇게 8개의 기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스를 래퍼 클래스(Wrapper class)라고 한다.
ex) Byte, short, Integer, Long, Float, Double, Character, Boolean
래퍼 클래스는 산술 연산을 위해 정의된 클래스가 아니므로, 인스턴스에 저장된 값을 변경할 수 없다. 단지, 값을 참조하기 위해 새로운 인스턴스를 생성하고, 생성된 인스턴스의 값만을 참조할 수 있다. 기본 타입의 데이터를 래퍼 클래스의 인스턴스로 변화하는 과정을 박싱(Boxing), 래퍼 클래스의 인스턴스에 저장된 값을 다시 기본 타입 데이터로 꺼내는 과정을 언박싱(UnBoxing)이라고 한다.
●추상클래스
: abstract 키워드를 가진 추상 메서드를 하나 이상 가진 클래스이다. 추상 메서드는 구현부가 없이 선언부만 있어 완전하지 않은 메서드를 의미한다. 완전하게 구현되지 않고 일부분만 구현되어있는 클래스이므로 직접 객체 생성 불가, 클래스를 상속받아 추상 메서드를 오버라이딩하여 사용해야 된다. 즉) 자식 클래스에게 강제성을 부여한다.
추상 메서드 : abstract 반환타입 메서드이름(); // 이렇게 선언부만 있고 구현부가 없다.
●인터페이스
: 일종의 추상클래스로 오직 추상메소드와 상수만 멤버로 가진다. implements 키워드 사용해서 인터페이스를 구현한다. 단일 상속 특징과 달리 다중 구현이 가능하다. 인터페이스를 사용하는 이유는 정형화된 틀 안에서 클래스를 개발할 수 있다. 여러 개발자가 하나의 시스템을 개발할 때 공통적인 클래스 개발, 구현 객체의 같은 동작을 보장하기 위한 목적이다.
●추상클래스 vs 인터페이스
- 공통점 : new 연산자로 인스턴스 생성 불가능하여 스스로 객체가 될 수 없다. 사용하기 위해서는 하위 클래스에서 확장 및 구현해야한다. 객체 지향 프로그래밍의 다형성을 잘 보여준다.
- 차이점 : 추상 클래스는 일반 메서드를 사용 가능하지만, 인터페이스는 메서드 선언만 가능하다. 추상 클래스의 목적은 추상 메서드를 자식 클래스가 구체화하여 그 기능을 확장하는 목적이 있다. 즉) 공통된 부분은 추상 클래스에서 정의하고 자식 클래스들은 추가적으로 필요한 부분을 추가해서 그 기능을 확장해 나가는 것이다. 하지만 인터페이스는 서로 관련 없는 클래스에서 공통적으로 사용하는 방식이 필요하지만 기능을 각각 구현할 필요가 있는 경우 사용.
다시 말하자면 추상 클래스는 미완성 설계도라고 표현할 수 있다. 상속을 통해 자손 클래스에서 완성하도록 유도하는 클래스이다. 인터페이스는 기본 설계도라고 할 수 있다. 추상 클래스처럼 다른 클래스를 작성하는데 도움을 주는 목적으로 사용한다.
추상 클래스는 상속 관계를 쭉 타고 올라갔을 때 같은 조상 클래스를 상속하는데 기능까지 완벽히 똑같은 기능이 필요한 경우 사용하고 인터페이스는 상속 관계를 쭉 타고 올라갔을 때 다른 조상 클래스를 상속하는데 같은 기능이 필요할 경우 사용한다.
위와 같이 생명체라는 클래스는 인간과 동물의 최상위 부모 클래스이다. 인관과 동물은 각각 사람 클래스와 다양한 동물 클래스들의 부모가 된다. 여기서 만약 kevin과 turtle이 모두 수영을 할 수 있다고 가정할때 그럼 생명체라는 클래스에다 수영하다라는 메서드들을 만들어줘야할까?? 그렇게 되면 모든 인간과 모든 동물은 수영을 할 줄 알아야되는데, 그렇지 못한 생명체들도 많다. 이럴때 사용하는 것이 바로 인터페이스이다. 인터페이스로 따로 선언을 해줘서 각각 수영을 할 수 있는 클래스에 구현시켜주면 가독성도 좋고 유지보수하는 측면에서도 뛰어나다.
● 오버로딩 vs 오버라이딩
- 오버로딩 (Overloading) : 같은 이름의 메서드를 매개변수의 타입이나 개수가 다르게 하여 여러 개 정의하는 것. return type과 접근제어자는 영향을 주지 않는다.예를들어 println이 대표적인 예시이다.
- 오버라이딩 ( Overriding) : 상속에서 ㅅ나온 개념으로, 상위(부모) 클래스의 메서드를 하위(자식) 클래스에서 재정의하는 것.
● 다형성
: 자바에서 다형성은 상속(오버라이딩)과 인터페이스를 통해 이루어진다. 하나의 객체를 다양한 타입으로 사용할 수 있게 한다. 코드의 재사용성, 개발자의 편의성, 유지보수의 편리함. 예를들어 키보드에서 esc와 enter는 누른다라는 같은 동작을 통해 실행되지만 취소, 입력이라는 다른 실행 목적을 가진다.
● GC 가비지컬렉터이란?
: 자바의 메모리 관리 방법 중 하나로 JVM의 Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 주기적으로 삭제하는 프로세스를 말한다. C나 C++에서는 이러한 가비지 컬렉터 없어 프로그래머가 수동으로 메모리 할당과 해제를 해줘야 하는 반면 Java는 JVM에 탑재되어 있는 가비지 컬렉터가 메모리 관리를 대행해주기 때문에 개발자는 개발에만 집중할 수 있다.
단점으로는 개발자가 메모리가 언제 해제되는지 정확히 알 수 없고, 가비지 컬렉션이 동작하는 동안 다른 동작을 멈추기 때문에 오버헤드가 발생한다. 따라서 GC가 너무 자주 실행되면 소프트웨어 성능 하락의 문제가 되기도 한다.
● 자바의 메모리 구조
- 메소드 영역 : static 변수, 전역변수, 코드에서 사용되는 class 정보들 저장한다. 프로그램의 시작부터 종료까지 메모리에 남아있는다.
- 스택 ( stack) : 지역변수, 함수, 메서드 등이 저장되는 LIFO 방식의 메모리영역이다. 메서드가 호출될 때 메모리에 할당되고 종료되면 메모리가 해제된다. 새로운 데이터가 할당되면 이전 데이터는 지워진다.
- 힙 ( Heap) ; new 연산자를 통한 동적 할당된 객체들이 저장. 가비지 콜렉터에 의해 메모리 관리가 된다.
메소드 영역은 JVM이 동작해서 클래스가 로딩될때, Stack은 컴파일 타임 시 할당, Heap은 런타임시 할당된다.
● Call by Rerence / Call by Value
- call by reference: 참조에 의한 호출, 메서드 호출 시에 사용되는 인자의 메모리에 저장되어 있는 주소 복사 > 자바
- call by value : 값에 의한 호출, 메서드 호출 시 사용되는 인자의 메모리에 저장되어 있는 값 복사
● Error와 Exception의 차이
에러는 실행 중 일어날 수 있는 치명적인 오류를 말한다. 컴파일 시점에 체크할 수 없고, 오류가 발생하면 프로그램은 비정상 종료되며 예측 불가능한 UnchekedException에 속한다. ( IOException, ClassNotFoundException ... )
반면 Exception은 error 보다 비교적 경미한 오류이며, try-catch를 이용해 프로그램의 비정상 종료를 막을 수 있다. ( NullpointerException, ArrayIndexOutOfBoundException ..._
● 배열과 컬렉션의 차이점
: 배열은 하나의 자료형만 저장이 가능하고 고정된 크기이지만 컬렉션은 복수의 자료형 저장이 가능하고 가변적 크기를 갖는다. 배열은 정적 메모리 영역에 있기 때문에 데이터가 가변적일 수 없고, List는 동적 메모리 영역에 있기 때문에 데이터가 가변적으로 늘어날 수 있다.
● 컬렉션 (Collection)
: 컬렉션, 다수의 데이터를 다루는데 필요한 다양하고 풍부한 클래스를 제공하며 자료구조를 직접 구현하지 않고 편하게 사용이 가능하다. 인터페이스와 다형성을 이용한 객체지향적 설계를 통해 표준화되어 있어 재사용성이 높은 코드를 작성할 수 있다.
● 컬렉션 대표 인터페이스
인터페이스 특징 List 순서가 있는 데이터의 집합, 데이터의 중복을 허용한다.
ex) 대기자 명단구현 클래스 : ArrayList, LinkedList, Stack, Vector 등
ArrayList : 배열에 데이터를 저장, 단방향 포인터 구조, 각 데이터에 대한 인덱스를 가지며데이터 검색에 적합하나 데이터의 삭제 삽입에는 부적합하다.
LinkedList : 양방향 포인터 구조, 데이터 삽입/삭제 시 노드의 주소만 바꾸면 되므로 적합
Vector : ArrayList와 동일하게 사용이 가능한 리스트로 동기화를 보장한다. 다만 용량 크기가 커서 잘 사용되지 않음Set 순서를 유지하지 않는 데이터의 집합, 데이터의 중복을 허용하지 않는다.
ex) 양의 정수 집합, 소수의 집합구현 클래스 : HashSet, TreeSet 등
HashSet : 저장 순서를 유지하지 않는 데이터 집합으로 해시 알고리즘 사용으로 검색 속도가 빠르다.
LinkedHashSet : 넣은 순서대로 값을 담음으로 순서를 가진다.
TreeSet : 데이터가 정렬된 상태로 저장되는 이진 탐색 트리 형태로 요소 저장한다.Map 키(key)와 값(value)의 쌍(pair)으로 이루어진 데이터의 집합
순서는 유지되지 않으며, 키는 중복을 허용하지 않고, 값은 중복을 허용한다.
ex) 우편번호, 지역번호구현 클래스 : HashMap, TreeMap, Hashtable, Properties 등
HashMap : 배열과 연결이 결합된 형태 모든 방면에서 뛰어난 형태 검색에 최고성능 보인다. (순서를 갖지 않는다.)
LinkedMap : 순서대로 담겨 순서를 가진다.
TreeMap : key 값에 의해 정렬되며 순서를 갖지 않는다.● 스택(Stack)과 큐(Queue)
스택 : 마지막에 저장한 데이터를 가장 먼저 꺼내게 되는 LIFO구조, 즉) 꺼내면 데이터가 역순이 된다. ArrayList 적합
ex) 웹브라우저의 뒤로/ 앞으로 , 수식 괄호 검사
큐 : 처음 저장한 데이터를 가장 먼저 꺼내게 되는 FIFO구조. LinkedList 적합
ex) 최근 사용한 문서, 인쇄작업 대기목록
● Iterator
: Iterator는 컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스이다. 컬렉션 프레임웍에서 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화하였다.
●직렬화(Serialize)란?
: 객체를 직렬화하여 전송 가능한 형태로 만드는 것을 의미한다. 객체들의 데이터를 연속적인 데이터로 변형하여 Stream을 통해 데이터를 읽도록 해준다. 주로 객체들을 통째로 파일로 저장하거나 전송하고 싶을 때 주로 사용된다. Serializable을 implements하면 멤버변수 전부 직렬화 대상이 되는데 만약 직렬화 대상에서 제외하고 싶다면 변수명 앞에 transient를 붙인다.
●역직렬화(Deserialization)는?
: 직렬화된 파일 등을 역으로 직렬화하여 다시 객체의 형태로 만드는 것을 의미한다. 저장된 파일을 읽거나 전송된 스트림 데이터를 읽어 원래 객체의 형태로 복원한다.
● Annotation
: 자바 코드에 주석처럼 달아 클래스에 특수한 의미를 부여하거나 기능을 주입할 수 있는 인터페이스. JDK에 내장되어 있거나, 어노테이션에 대한 정보를 나타내거나 개발자가 직접 만들 수 있다. @Override가 대표적인 어노테이션이다.
● final
: 초기값 저장시 최종적인 값이 되어서 프로그램 실행 중 수정할 수 없는 필드이다.
- final class : 다른 클래스에서 상속하지 못하는 클래스
- final method : 다른 메소드에서 오버라이딩하지 못하는 클래스.
- final variable : 변하지 않는 상수값이 되어 새로 할당할 수 없는 변수.
- static final : 상수. 불변의 값
● 정적멤버 (static)
: 클래스가 로딩될 때 메모리 공간을 할당하는데 처음 설정된 메모리 공간이 변하지 않음을 의미한다. 객체를 생성하지 않고도 사용할 수 있는 필드와 메서드로 객체마다 가지고 있을 필요성이 없는 공용 데이터라면 정적 필드로 선언한다. static을 붙여 구분한다.
● String vs StringBuffer vs StringBuilder
String의 특징은 new 연산을 통해 생성된 인스턴스 메모리 공간은 변하지 않는다. . +, concat과 같은 연산시 메모리의 내용이 변하는 것이 아니라 새로운 String 인스턴스가 생성된다. heap 영역에 저장되므로 Garbage Collector로 제거되어야 한다 . 문자열 연산이 많아지는 경우 성능이 떨어진다. 따라서 문자열 연산이 적고, 조회가 많은 멀티스레드 환경에서 좋다.
StringBuffer, StringBuilder
공통점
- new 연산으로 클래스를 한번만 만든다. (Mutable)
- 문자열 연산 시 새로 객체를 만들지 않고 크기를 변경한다.
- 클래스의 메소드가 동일하다.
차이점
StringBuffer는 Thread Safe하다. 즉 멀티쓰레드 환경에서 synchronize 키워드가 가능하므로 동기화가 가능하다.
StringBuilder는 Thread Safe하지 않다. ( 여러 쓰레드에 참조되지 않는 경우 빌더가 성능이 더 좋다. )
● 제너릭 Generic
: 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법. 코드의 안전성과 재사용을 위한 기능으로, 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안전성을 높이고 형변환의 번거로움을 줄여준다.
ex) ArrayList<String>과 같은 명시적인 표현을 통해 ArrayList 객체 내부에 어떤 형태의 클래스가 있는지 확인 가능하므로 불필요한 형 변환 코드 사용을 줄이고 오류를 줄일 수 있다. 제너릭이 존재하지 않았다면 StringArrayList , IntegerArrayList와 같이 각각의 데이터 타입을 제공하는 ArrayList 클래스가 필요했을 것이다.
반응형'취업준비 > 기술면접' 카테고리의 다른 글
[기술면접 Spring] Filter, Interceptor, AOP 차이점 (1) 2022.09.20 [기술면접 JAVA] 캡슐화와 은닉화의 차이점 (0) 2022.09.19 [기술면접 OS] 프로세스와 스레드의 개념과 차이점 (0) 2022.09.19 [기술면접 JAVA] 클래스변수와 인스턴스변수 차이점, static 키워드 (1) 2022.09.13 [웹개발 기술면접] 모델1, 모델2와 MVC 패턴 알아보기 (0) 2022.09.13