춤추는 개발자

[Java] 신입 개발자의 면접 준비 본문

Small talk/면접 준비

[Java] 신입 개발자의 면접 준비

Heon_9u 2021. 4. 12. 21:30
728x90
반응형

String, StringBuilder, StringBuffer의 차이를 설명해보세요.

- String 객체는 immutable 합니다. 즉, 한번 생성이 되면 변경이 불가능합니다.

반면에, StringBuilder와 StringBuffer의 차이점은 멀티쓰레드 상태에서 동기화의 지원 여부가 다릅니다.

StringBuffer는 멀티쓰레드 환경에서 동기화를 보장하지만, StringBuilder는 동기화를 보장하지 않습니다.

 

추가적으로 설명하자면, String과 StringBuilder는 원래 문자열을 합치는 과정에서 성능차이가 있었지만, JDK 1.5버전 이후부터는 String을 "+"연산할 경우, 동적으로 StringBuilder로 컴파일하여 실행되므로 성능차이가 사라졌습니다.

 


객체지향 프로그래밍(OOP)에 대해서 설명해보세요.

 프로그래밍에 필요한 데이터를 추상화시켜서 상태와 행위를 가진 객체로 만들고 이를 기반으로 프로그래밍하는 것.

장점은 코드 재사용이 용이(남이 만든 클래스를 가져와서 이용 가능), 유지보수가 쉬움(클래스 내부의 멤버 변수 or 메서드를 수정)

단점은 객체가 많을 수록 용량이 커지고, 설계시 많은 노력과 시간이 필요

객체지향의 특징 5가지는 크게 클래스+인스턴스(객체), 상속, 추상화, 캡슐화, 다형성

 

클래스: 실제 사물의 속성과 행위를 추상화하여 변수와 메서드로 정의한 것.

인스턴스(객체): 클래스를 자료형으로 갖는 변수로, 클래스에서 정의한 것을 토대로 실제 메모리를 할당받은 데이터

 

상속: 하위 클래스가 상위 클래스의 속성과 메서드를 이어받아 사용하거나, 기능의 일부를 수정하여 사용하는 것

추상화: 객체들의 공통의 특징인 속성이나 기능을 묶어 이름은 붙이는 것, 객체 지향 관점에서는 클래스를 정의하는 것

캡슐화: 데이터와 데이터를 처리하는 메서드를 하나로 그룹화, 코드를 재수정없이 재활용, 객체지향 관점으로 본다면 기능과 특성의 모음을 '클래스'라는 '캡슐'에 분류하는 것.

다형성: 동명의 메서드를 다른 인자나 리턴값을 통해 재정의 하는 것(오버라이딩, 오버로딩). 즉, 상황에 따라 다르게 사용하는 것.

 


오버로딩과 오버라이딩에 대해 설명해보세요.

오버로딩: 같은 이름의 함수를 매개변수의 타입과 개수 또는 리턴값을 다르게 하여 재정의 하는 것. 예를 들어 연산자 오퍼레이션이 있다.(숫자는 더하기, 문자열은 합치기)

오버라이딩: 상위 클래스의 메서드를 재정의 하는 것으로 같은 이름과, 매개변수를 똑같이 해야한다.

 


getter, setter를 사용하는 이유

멤버변수를 private으로 지정하여 외부에서 직접 접근하지 못하게 하기위해, public으로 선언한 getter, setter를 사용한다. 이 과정에서 메서드를 통해 멤버변수에 접근하기 때문에 setter 안에서 올바르지 않은 입력에 대해 사전에 처리할 수 있다는 장점이 있다.

 


Java의 바이트 코드에 대해 설명해보세요. ( + Java의 장점)

Java의 소스 코드가 변환된 코드로 자바 가상 머신이 이해할 수 있는 언어입니다. 바이트 코드의 확장자는 .class로 Java 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트라서 Java 바이트 코드라고 불리고 있다. 이러한 Java 바이트 코드는 JVM만 설치되어 있으면, 어떤 OS에서도 실행될 수 있다.

 


NIO (New Input-Output)에 대해 설명해보세요.

 

 


Java의 기본 자료형과 참조 자료형에 대해 설명해보세요.

기본 자료형: Primitive type이라고도 하며 메모리 영역 중, Stack 영역에 실제 값을 저장하는 데이터 타입으로 int, char, boolean 등이 있습니다.

참조 자료형: 기본형 외에 모든 타입으로 String, Class 등 모든 변수는 잠조형 변수입니다. 새로 선언할 때는 heap영역에 저장공간을 확보하며 항상 new로 정의합니다. 실제 값은 heap영역에 저장하고 메모리 주소값은 stack영역에 저장됩니다.


Garbage Collector란 무엇인지 설명해보세요.

 객체들 중, 접근되어지지 않은 객체들을 메모리에서 제거하여 메모리 공간을 확보하는 기법입니다. 이러한 과정을 Mark and sweep라고 하며 JVM의 Garbage Collector가 Stack의 모든 변수를 스캔하면서 어떤 객체를 레퍼런스하는지 Mark합니다. 이후, Mark되지 않은 객체들을 메모리에서 제거하는 sweep과정이 일어나게됩니다. 이때, mark하는 과정에서 모든 스레드가 중단되기 때문에 무분별하게 System.gc()를 통한 Garbage Collection을 호출하면 안된다.


'=='과 Equals()의 차이점

==은 비교를 위한 연산자로 비교하고자 하는 대상의 주소값을 비교합니다. 그래서 기본형 변수를 비교할 때 사용합니다. 반면에, equals()는 메소드로 객체들끼리 내용을 비교할 수 있도록 합니다. 비교하고자 하는 대상의 내용 자체를 비교합니다. 이는 객체를 비교할 때 사용합니다.


Java의 Call by value와 Call by Reference에 대해서 설명해보세요.

Call by Value: 값에 의한 호출로 일반적으로 함수 호출 형태에서 값을 복사하는 것

Call By Reference: 참조에 의한 호출로 간단하게 변수의 주소를 전달하는 것입니다. 그러나 Java의 경우, Call by Value만 이루어지고, C언어에서 포인터를 통한 Call By Reference가 사용됩니다.

 


접근 제어자(Access Modifier)에 대해 설명해보세요.

클래스의 변수나 메소드를 외부에서 접근하거나 접근하지 못하도록 막기위해 접근 제어자를 활용합니다. 이를 통해 프로그래머의 코딩 실수를 방지하거나, 기타 위험 요소나 에러들을 사전에 막을 수 있는 장점이 있습니다.

private: 변수나 메소드를 해당 클래스에서만 접근이 가능하도록 하는 것, 보통 Class의 멤버변수를 private으로 지정한다.

default: 접근제어자가 없는 경우, 해당 패키지 내에서만 접근이 가능

protected: 변수나 메소드를 동일 패키지 내의 클래스 또는 해당 클래스를 상속받은 외부 패키지의 클래스에서 접근이 가능하다.

public: 변수나 메소드가 어떤 클래스라도 접근이 가능하다.

 


추상 클래스(abstract)와 인터페이스(Interface)에 대해 설명해보세요.

 클래스는 크게 일반 클래스와 추상 클래스 2가지로 나눌 수 있는데, 추상 클래스는 클래스 내에 '추상 메서드'가 하나 이상 포함되거나 abstract로 정의된 경우를 말합니다. 추상 클래스는 상속을 통해 기능을 이용하고, 확장시키는데 활용합니다. (미완성 설계도)

 인터페이스는 안이 비어있는 메소드들의 형태만 정의한 것입니다. 인터페이스를 상속하는 클래스들은 인터페이스의 모든 메소드들을 재정의 및 구현해야만 합니다. 이는 객체들의 같은 동작을 보장하기 위해 사용합니다. 

 이를 통해 둘 사이 공통점은 추상 메서드를 사용한다는 것, 차이점은 사용 용도라고 볼 수 있습니다. Java의 특성상 한개의 클래스만 상속이 가능하지만, 인터페이스는 다중 상속이 가능합니다. 그래서 추상 클래스는 객체를 분류하고 인터페이스는 객체가 할 수 있는 기능들을 인터페이스로 구현합니다.

 예를 들어 생명체라는 클래스를 상속하는 동물, 사람 클래스가 있다고 가정합니다. 여기서 동물 클래스를 상속하는 물고기 클래스와 사람 클래스를 상속하는 제임스 클래스가 있다고 가정하겠습니다. 이때, 물고기와 제임스가 모두 수영할 수 있음을 코드로 추가하고자 할 때, 인터페이스를 활용하는 것입니다.

 즉, 두 객체의 상속 관계를 쭉 타고 올라갔을 때, 같은 조상클래스를 상속하고 기능까지 완벽히 똑같으려면 추상 클래스를 사용합니다. 반면에, 두 객체의 조상 클래스가 다르고, 같은 기능(메소드)이 필요한 경우 인터페이스를 사용하는 것입니다.


컬렉션이란 무엇인가요.

Java의 컬렉션이란 객체들을 모아놓고 관리하기 위해 사용하는 집합으로써 List, Set, Map이 있습니다. List는 객체를 일렬로 배치하여 탐색에 유리한 ArrayList와 추가, 삭제에 유리한 LinkedList가 있습니다. Set과 Map의 경우 객체의 중복없이 데이터를 저장한다는 특징이 있으며, Map은 <key, value>형태의 데이터를 저장합니다.

 


컬렉션(Collection) 클래스에서 제네릭(Generic)을 사용하는 이유를 설명해보세요.

 Generic을 사용하는 이유는 해당 컬렉션이 사용할 객체의 타입을 지정하기 위해 사용합니다. 이는 컬렉션에 데이터를 추가할 때마다 객체의 형변환을 할 필요 없게하고 명시적으로 해당 컬렉션의 데이터 타입이 무엇인지 알 수 있게 해줍니다. (Generic은 자바 1.5버전 부터 추가된 것으로 꺽쇠 기호(<>)로 추가되며 특정 형식을 지정하여 사용합니다.)

 


Generic에 대한 추가적인 설명

Generic은 다형성 개념을 사용할 수 있습니다. 즉, 클래스와 인터페이스에서도 사용될 수 있습니다. 예를 들어, A클래스를 상속받은 B, C클래스가 있는 경우, A 클래스를 매개 변수로 선언한 컬렉션에 A, B, C 클래스로 만들어진 객체를 저장할 수 있습니다. 

 


Wrapper Class에 대해 설명해보세요.

기본 자료형을 객체로 다루기 위해서 사용하는 클래스들을 Wrapper Class라고 합니다. 대표적으로 기본형 int의 Wrapper Class인 Integer가 있는데, 이를 사용하는 이유는 매개변수를 객체로만 갖는 컬렉션에 int형을 저장하고 싶은 경우, int 대신 Integer를 사용하며 컬렉션을 선언할 수 있습니다.


Java에서 쓰레드를 구현하기 위한 2가지 방법은 무엇인가요.

 Thread 클래스를 상속받거나 Runnable 인터페이스를 구현하는 2가지 방법이 있습니다. Thread 클래스를 상속받는 경우, run() 메소드를 오버라이딩하여 사용합니다. Runnable 인터페이스는 구현할 메소드가 run() 메소드 하나뿐인 함수형 인터페이스입니다. 람다식을 이용해서 좀 더 깔끔하게 구현할 수 있습니다.

 실행 방법에 차이가 있습니다. Thread 클래스를 상속받은 경우, 해당 객체에서 start()메소드로 직접 실행할 수 있습니다. 반면에, 인터페이스로 구현한 경우, 별도의 Thread 객체를 생성하여 start()메소드를 호출해야 Thread를 실행할 수 있습니다.


쓰레드 풀이란 무엇인가요.

이미 스레드가 생성되어있는 풀장을 의미합니다. 작업할 떄마다 새로운 스레드를 생성하고 다시 수거하는 과정에서 프로그램 성능에 문제를 줄 수 있기 때문에 스레드를 미리 만들어 놓은 것입니다. 즉, 프로그램의 성능 저하를 방지하고 다수의 사용자 요청을 처리하기위해 사용합니다.

 Java에서는 concurrent라는 패키지에서 ExecutorService 인터페이스나 Executors 클래스를 통해 스레드 풀을 사용할 수 있습니다.

 단점: 과유불급, 쉬고 있는 스레드 발생(이를 방지하기 위한 forkJoinPool을 지원)

 


forkJoinPool이란 무엇인가요

 쓰레드 풀에서 발생하는 단점 중, 쉬고 있는 스레드를 방지하고 모든 스레드가 공평하게 일을 하기위해 사용됩니다. 큰 업무를 작은 업무로 나눠서 스레드에 배분하고 이를 다시 취합하는 형태입니다. 또는 스레드가 다른 스레드의 일을 가져와서 처리하기도 합니다. 이러한 과정이 forkJoinPool이라고 합니다.

 


Java EE와 SE의 차이점은 무엇인가요.

SE는 가장 보편적으로 쓰이는 Java API 패키지입니다.

EE는 SE를 기반으로 Java를 이용한 서버측 개발을 위한 플랫폼. 엔터프라이즈 환경을 위한 도구로 어플리케이션 개발에 주로 사용됩니다. 웹 프로그래밍에 필요한 JSP, Servlet, JDBC 등이 포함되어 있습니다.

 


객체와 클래스의 차이점은?

클래스는 객체를 정의해놓은 것으로, 객체의 틀이라고 정의할 수 있습니다.

객체는 클래스를 자료형으로 갖는 것으로 클래스에 정의된 내용대로 메모리에 생성된 것을 뜻합니다.

예로 들면 붕어빵 틀이 클래스가 되고, 붕어빵이 객체가 되는 것입니다.

 


Java의 메모리 영역에 대해 설명해보세요.

 Java의 메모리 영역은 static, stack, heap영역으로 구분할 수 있습니다.

 static 영역은 패키지나 클래스의 정보가 저장됩니다. 또한, static 키워드를 통해 선언된 변수나 메소드도 static영역에 저장됩니다. static 영역에 있는 것들은 어디서나 접근이 가능하기 때문에 '전역'이라는 키워드를 사용합니다. 만약, 실제 IT제품에서 사용할 경우, 읽기 전용이 아닌 변수에 경우 static을 사용하면 안됩니다.

 stack 영역은 메소드가 실행되거나 조건문, 반복문을 수행할 때마다 stack 프레임이 생기게 됩니다. 내부에서 선언된 지역변수는 stack 영역에 저장되며, 기본형 타입 변수의 값들과 참조형 타입 변수의 참조 값만 stack 영역에 저장됩니다.(객체의 주소값) 쓰레드도 stack 영역에서 생성됩니다.

 heap영역은 new연산자로 생성된 객체들(인스턴스)들이 저장됩니다. 그래서 stack 영역에서 참조값을 이용하여 참조형 변수가 heap영역에 있는 인스턴스를 참조하며 제어할 수 있게 됩니다. 만약, heap영역에 있는 인스턴스가 참조되지 않는 경우에는 GC에 의해 메모리에서 제거됩니다.

 


JSP와 Servelt이란?

JSP: Java Server Pages의 약자로 HTML코드에 Java코드를 넣어 동적 웹 페이지를 생성하는 도구, JSP가 실행되면 Java Servlet으로 변환됩니다.

Servlet: 웹 페이지를 동적으로 생성하기 위한 서버측 프로그램

 


String pool이란?

Java의 heap영역에서 String 객체들을 관리하는 공간입니다. 이는 HashMap의 형태로 String 객체를 생성하면 String pool에 같은 값을 갖는 String 객체가 있는지 검사하고 있으면 그 객체의 참조값을 사용합니다. 즉, String 객체를 생성하면 메모리 절약을 위한 캐싱이 이루어지는 것입니다. 물론, 모든 String이 String pool에 저장되진 않습니다. new 연산자로 생성한 String 객체는 Heap영역에 저장됩니다.

 String pool이 있는 이유는 String 타입은 불변성이라는 성질을 갖고 있기 때문입니다. (데이터의 신뢰성)

 


객체지향 프로그래밍의 5대 설계 원칙인 'SOLID'란?

1. 단일 책임 원칙(SRP)

2. 개방-폐쇄의 원칙(OCP)

3. 리스코프 치환 원칙(LSP)

4. 인터페이스 분리 원칙(ISP)

5. 의존 역전 원칙(DIP)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형