Study/Tech Interview

Java 면접

by somida 2021. 5. 28.
반응형

Java

장점

  • 객체지향 언어
  • GC를 통해 자동 메모리 관리
  • 멀티 스레드 지원
    • 스레드 생성 및 제어와 관련된 라이브러리 API를 제공하고 있어 OS에 관계없이 멀티스레드 쉽게 구현 가능
  • OS에 독립적
    • JVM에서 동작하기 때문에 특정 OS에 종속되지 않음
  • 동적 로딩 지원
    • 각각의 객체가 필요한 시점에 클래스를 동적으로 로딩해 생성
    • 유지보수 시 해당 클래스만 수정하면 되기 때문에 유지보수가 쉽고 빠름

 

단점

  • 속도가 느림
    • 한 번의 컴파일이 아닌 JVM을 거쳐 기계어로 번역되기 때문에 C/C++과 같은 컴파일러 언어보다 느린 편
  • 예외 처리가 불편
    • 검사가 필요한 예외가 등장한다면 개발자가 예외 처리를 직접 해야 함

 

접근제어자

  • 굳이 알 필요 없는 정보를 숨기기 위해(정보 은닉) 접근제어자를 사용해 구체화
  • 멤버 또는 클래스에 사용 가능하며 외부에서 접근을 제한하는 역할을 함
  • private < default < protected < public 순으로 많은 접근 허용
private 외부에 공개되지 않고, 해당 클래스에서만 접근 가능
default 해당 패키지내에서만 접근 가능하며 생략 시 자동으로 default값으로 지정됨
protected 해당 패키지 또는 해당 클래스를 상속받은 외부 패키지의 클래스에서 접근 가능
public 어떠한 클래스에서든 접근 가능

 

데이터 타입

  • 기본형
    • 변수에 값 자체를 저장하며 사용하기 전에 반드시 선언되어야 함
    • 비 객체 타입이며 Null 값 비허용
    • 데이터 크기가 작고 고정적이라 stack 영역에 저장됨
    • byte, short, int, long (정수형) / float, double (실수형) / char(문자형) / boolean(논리형)
  • 참조형
    • 기본형을 제외한 모든 형태로 객체가 존재하는 주소를 저장
    • 데이터 크기가 가변적이고 동적이라 heap 영역에 저장되고, stack에는 메모리 주소만 저장됨
    • 클래스 / 배열 / 인터페이스
  • 암시적 형 변환(묵시적 형 변환)
    • 작은 범위에서 더 넓은 범위로의 형 변환
    • 더 넓은 범위로 데이터를 저장하기 때문에 데이터 손실이 없음
  • 명시적 형 변환
    • 더 넓은 범위에서 작은 범위로의 형 변환
    • 데이터의 손실이 발생할 수 있으므로 명시적으로 형 변환 연산자를 사용해야 함
// 암시적 형변환
int a = 10;
double b = a;

// 명시적 형변환
double a = 3.14;
int b = (int)a;

 

Java와 C/C++ 차이

  Java C / C++
공통점 Java를 설계할 때 C++개발자들이 쉽게 배울 수 있도록 설계했기 때문에 문법적으로 상당히 유사함
컴파일 JVM이라는 가상머신에서 컴파일 바로 각 OS에 맞는 기계어로 컴파일
속도 느린 편 빠른 편
다중 상속 X (인터페이스는 다중 상속 가능) O
메모리 관리 GC가 자동 관리 수동 관리
설계 목표 보안, 빠른 이식성에 집중 실행속도, C언어와의 하위 호환성에 집중

 

Java 동작 과정

  1. 개발자가 자바 파일(. java)을 생성
  2. 자파 컴파일러가 자바 소스파일을 컴파일해 바이트코드(. class)를 생성
  3. 컴파일된 바이트 코드를 JVM의 Class Loader에게 전달
  4. 클래스 로더는 동적 로딩을 통해 필요한 클래스들을 로딩해 Runtime Data Area(JVM의 메모리 영역)에 적재
    • 클래스 로더 세부 동작
      • 로드 : 클래스 파일을 가져와 JVM의 메모리에 적재
      • 검증 : 자바 언어 명세 및 JVM 명세에 명시된 대로 구성되어 있는지 검사
      • 준비 : 클래스가 필요로 하는 메모리를 할당 (필드, 메서드, 인터페이스...)
      • 분석 : 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경
      • 초기화 : 클래스 변수들을 적절한 값으로 초기화(static 필드)
  5. 실행 엔진은 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행

 

Java 메모리 영역

  • Method Area : 클래스 정보(static 변수, 전역 변수..)가 포함되어 있고, 객체의 동작에 해당하는 실행 블록
  • Heap Area : new연산자를 통해 동적 할당된 객체들이 저장되며 GC에 의해 메모리 관리
  • Stack Area : 지역변수, 메서드 등이 할당되는 LIFO 방식의 메모리

 

Collection

다수의 Data를 다루는데 표준화된 클래스들을 제공해주기 때문에 자료구조를 직접 구현하지 않고 편하게 사용

배열과 달리 객체를 보관하기 위해 미리 할당받지 않고 동적으로 할당받을 수 있으므로 공간 효율성을 높여줌

List 순차적으로 데이터 저장
데이터 중복 허용, 데이터 NULL 허용
ArrayList, LinkedList
Map 순서 없이 Key, Value로 데이터 저장
Key 중복 비허용, Key NULL 비허용, Value 중복 허용
HashMap, LinkedHashMap
Set 순서 없이 Key로만 데이터 저장
Key 중복 비허용, Key NULL 비허용
HashSet, LinkedHashSet
Collection에서 Generic을 사용하는 이유
컬렉션 클래스에서 제네릭을 사용하면 컴파일러는 특정 타입만 포함될 수 있도록 컬렉션을 제한
컬렉션 클래스에 저장하는 인스턴스 타입을 제한해 런타임에 발생할 수 있는 모든 예외를 컴파일 타임에 잡도록 도와줌

 

Vector와 ArrayList

동적인 배열을 사용할 때 주로 사용하는 클래스

  • Vector
    • 필요에 따라 크기를 동적으로 조절할 수 있는 동적 배열
    • 배열과 마찬가지로 정수 인덱스를 통해 배열에 액세스 가능
    • 동기화 지원(멀티스레드 환경 지원)
    • 속도가 느리지만 병렬 상황에서 안전(Thread-Safe)
    • 크기가 증가하는 경우 2배로 증가
  • ArrayList
    • 동기화 미지원
    • 동시에 여러 스레드가 액세스 가능
    • 속도는 빠르지만 병렬 상황에서 안전하지 않음(Thread-Safe X)
    • 크기가 증가하는 경우 1.5배로 증가
Thread-Safe
멀티스레드 프로그래밍에서 여러 스레드가 동시에 접근이 이뤄져도 프로그램 실행에 문제없음
Vector는 동기화되어있기 때문에 한 번에 하나의 스레드만 접근할 수 있어서 안전함

멀티스레드 환경이 아닌 경우 ArrayList를 사용하는 것이 바람직

 

Annotation

주석과는 역할이 다르지만 주석처럼 코드에 달아 클래스에 특별한 의미를 부여하거나 기능을 주입할 수 있음

이 속성을 어떤 용도로 사용할지? 이 클래스에 어떤 역할을 줄지 결정해서 붙이는 것

프로그램에게 추가적인 정보를 제공하는 메타데이터와 같은 역할

  • 종류
    • @Override : 선언한 메서드가 오버라이드 되었다는 의미
      • 상위 크래스에서 해당 메서드를 찾을 수 없다면 컴파일 에러 발생
    • @Deprecated : 해당 클래스는 더 이상 사용할 수 없음
    • @SuppressWarnings : 컴파일러의 경고를 억제 시킴

 

Generic

클래스 내부에서 사용할 데이터 타입을 인스턴스 생성 시에 결정하는 방식

제네릭 타입을 이용해 컴파일 과정에서 타입 체크를 할 수 있음

  • 목적
    • 제네릭을 사용하지 않으면 빈번한 타입의 변환이 발생될 수 있어 성능 저하 우려
    • 제네릭을 활용하면 따로 형 변환할 필요가 없고, 타입 에러가 발생하지 않기 때문에 유용하게 사용
  • 장점
    • 컴파일할 때 타입을 체크해 에러 사전 방지
Template
C++에서 사용하는 기능으로 하나의 클래스를 서로 다른 여러 타입에 재사용할 수 있도록 하는 기법

 

Final Keyword

  • final : 변수나 메서드 또는 클래스가 변경 불가능하도록 만듦
  • finally : try/catch블록이 종료될 때 항상 실행될 코드 블록을 정의하기 위해 사용
  • finalize() : GC가 더 이상의 참조가 존재하지 않는 객체를 메모리에서 삭제하겠다고 결정하는 순간 호출됨
final class 다른 클래스에서 상속하지 못함
final method 다른 메소드에서 오버라이딩하지 못함
final variable 변하지 않는 상수값이 되어 새로 할당할 수 없는 변수가 됨
finally 예외가 발생하더라도 항상 실행
finalize() GC에 의해 호출되는 함수로 절대 호출해서는 안되는 함수

 

직렬화(Serialization)

Java 시스템 내부에서 사용되는 Object를 외부의 Java 시스템에서도 사용할 수 있도록 Byte형태로 데이터 변환하는 기술

  • 역직렬화(Deserialize) : Byte로 변환된 데이터를 원래대로 Object나 Data로 변환하는 기술
  • 장점
    • 자바 직렬화는 자바 시스템의 개발에 최적화되어있음
    • 복잡한 데이터 구조 클래스의 객체라도 직렬화 기본 조건만 지키면 간단하게 직렬화/역직렬화 가능

 

클래스, 객체, 인스턴스

  • 클래스(Class)
    • 객체를 만들어내기 위한 설계도
    • 연관되어있는 변수와 메서드의 집합
  • 객체(Object)
    • SW 세계에 구현할 대상으로 클래스가 구체적인 실체인 인스턴스가 되었을 때 그것을 객체라고 함
    • 메모리에 할당된 실체화된 인스턴스
  • 인스턴스(Instance)
    • 설계도를 바탕으로 SW 세계에 구현된 구체적인 실체
    • 객체를 SW에 실체화한 것이 인스턴스
    • 실체화된 인스턴스는 메모리에 할당됨
    • 인스턴스는 객체에 포함된다고 볼 수 있음
객체 VS 인스턴스
객체는 현실세계에 가깝고, 인스턴스는 SW 세계에 더 가까움

 

문자열 클래스

  • String 
    • new 연산을 통해 생성된 인스턴스의 메모리 공간은 변하지 않음(Immutable)
    • Immutable 하기 때문에 연산 시 원본을 변경하지 않고 새로운 객체를 생성하기 때문에 메모리 공간 낭비 발생
    • GC로 제거되어야 함
    • 객체가 불변해 멀티스레드에서 동기화 신경 쓸 필요가 없음(조회 연산에 유리)
    • 문자열 연산이 적고 조회가 많은 멀티스레드 환경에서 효율적임
  • StringBuffer, String Builder
    • new 연산으로 클래스를 한 번만 만듦(Mutable)
    • 문자열 연산 시 새로 객체를 만들지 않고, 크기를 변경시킴
    • StringBuffer와 StringBuilder 클래스의 메서드가 동일함
    • StringBuffer는 Thread-Safe 하지만, StringBuilder는 Thread-Safe하지 않음
    • StringBuffer는 문자열 연산이 많은 멀티스레드 환경에서 효율적임
    • StringBuilder는 문자열 연산이 많은 싱글 스레드 환경 혹은 스레드를 신경 안 쓰는 환경에서 효율적임
  String StringBuffer StringBuilder
저장 영역 Heap or Constant String Pool Heap
 Mutable X (Immutable) O (Mutable)
Thread-Safe O O
멀티쓰레드 지원
X
멀티쓰레드 지원 X

 

리플렉션(Reflection)

컴파일러를 무시한 채 런타임 상황에서 메모리에 올라간 클래스나 메서드 등의 정의를 동적으로 찾아 조작할 수 있는 것

컴파일한 클래스 정보를 활용해 동적으로 프로그래밍 가능하도록 지원하는 API

  • 동적 언어의 특징
  • 프레임워크에서 유연성이 있는 동작을 위해 자주 사용
  • 실행시간에 다른 클래스를 동적 로딩해 접근할 때 사용
  • 클래스와 멤버 필드, 메서드 등에 관한 정보를 얻어야 할 때 사용
정적 언어 : 컴파일 시점에 타입 결정 ex) Java, C, C++...
동적 언어 : 런타임 시점에 타입 결정 ex) Python, Javascript, Ruby...

 

JavaEE와 JavaSE

JavaSE(Java Platform Standard Edition)

데스크톱, 서버, 임베디드를 위한 표준 자바 플랫폼으로 가장 일반적으로 사용됨

JDBC나 기본적인 기능 모두 포함되어 있기 때문에 Android개발에도 주로 사용

 

JavaEE(Java Platform Enterprise Edition)

자바를 이용한 서버 측 개발을 위한 플랫폼으로 기존 SE에 서버 측을 위한 기능을 추가해 SE의 모든 기능 이용 가능

 

JVM(Java Virtual Machine)

자바 코드를 컴파일해서 얻은 자바 바이트 코드를 해당 OS가 이해할 수 있는 기계어로 바꿔 실행시켜주는 역할

기능

  • Java가 OS와 관계없이 동작할 수 있도록 중개자 역할
  • GC 등의 기능 제공

구조

Class Loader 생성된 자바 바이트코드(.class)를 엮어 Runtime Data Area로 적재하는 역할을 실행
Execution Engine 메모리에 적재된 클래스(바이트코드)들을 기계어로 번역해 명령어 단위로 실행하는 역할
인터프리터 방식 / 컴파일러 방식
Garbage Collector Heap메모리 영역에 생성된 객체들 중 참조되지 않은 객체들을 탐색후 제거하는 역할
Runtime Data Area JVM이 운영체제로부터 할당받은 메모리 영역으로 사용되는 데이터들을 적재하는 영역
  • Runtime Data Area
    • Method Area : 클래스 관련 정보(클래스 변수의 이름, 타입, 접근제어자)와 static변수, 인터페이스 등이 저장됨
    • Heap Area : new를 통해 생성된 객체와 배열의 인스턴스 저장하는 곳. GC로 인해 메모리를 확보하는 곳
    • Stack Area : 메서드가 실행되면 이곳에 메서드의 영역이 1개 생김. 지역변수, 매개변수, 리턴 값 등이 저장됨
    • PC Register : 현재 스레드가 실행되는 부분의 주소와 명령을 저장
    • Native Method Stack : Java 이외의 언어로 작성된 코드를 위한 메모리 영역
멀티스레드 시 공유되는 메모리 영역
Method Area, Heap Area : 모든 스레드가 공유
Stack Area, PC Register, Native Method Stack : 각각의 스레드마다 생성되고 공유되지 않음

 

Garbage Collection(GC)

시스템에서 더 이상 사용하지 않는 동적 할당된 메모리 블록을 찾아 자동으로 다시 사용 가능한 자원으로 회수하는 것

연산에 의해 새롭게 생성된 객체 중 더 이상 참조되지 않는 객체를 정리하는 JVM 실행 엔진의 한 요소로 JVM에 의해 자동 실행

실행 시점

JVM이 메모리가 부족해지면 OS에서 추가로 메모리 요청을 할 때 GC가 실행됨

동작 과정

메모리를 정리하는 과정이기 때문에 일반적으로 메모리 사용을 중단한 채로 진행됨

  1. Stop-the-World
    • GC 실행 전 애플리케이션 실행을 멈추는 작업으로 GC를 실행하는 스레드를 제외한 모든 스레드가 작업을 멈춤
    • GC가 끝나면 다시 작업 재개
  2. GC 동작
    •  
    • 새로운 객체가 Eden영역에 할당
    • Eden이 가득 차면 MinorGC가 발생
    • MonorGC가 발생하면 Reachable 객체들은 Survival0으로 옮겨지고, Unreachable 객체들은 Eden영역이 클리어 될 때 함께 사라짐
    • 다음 MinorGC가 발생할 때 기존에 S0에 있던 객체들은 S1로 옮겨지고 age값이 증가됨
    • 살아남은 모든 객체들이 S1로 옮겨지면 S0과 Eden은 클리어 됨
    • 다음 MinorGC가 발생할 때 기존에 S1에 있던 객체들은 S0으로 옮겨지고 age값 증가됨
    • 위의 과정을 반복하다가 age값이 특정 이상이 되면 Old Generation으로 옮겨짐(Promotion)
    • Promotion과정이 계속 반복되면서 Old Generation이 가득 차게 되면 MajorGC가 발생


영역

  • Young Generation
    • 새롭게 생성한 객체들이 위치함
    • 대부분의 객체는 금방 접근 불가능 상태가 되므로 많은 객체가 Young영역에 생성되었다가 사라짐
    • 이 영역에서 객체가 사라질 때 MinorGC가 발생했다고 함
  • Old Generation
    • Young영역에서 계속 사용되어 살아남은 객체가 복사되는 영역
    • Young영역보다 크게 할당되며 더 적은 GC가 발생
    • 이 영역에서 객체가 사라질 때 MajorGC가 발생했다고 함
  • Permenant Generation : JVM에 의해 사용하는 클래스와 메서드 객체 정보를 담고 있음


Algorithm

  • Serial GC
    • Old영역에서 mark-sweep-compact라는 알고리즘 사용
    • 과정 : Old영역의 살아있는 객체 마킹(mark) → 힙의 앞부분부터 살아있는 것을 제외하고 sweep → 힙의 앞부분부터 채워서 객체 없는 부분과 있는 부분을 나눔(compact)
    • 적은 메모리와 CPU 코어가 적을 때 적합하여 32bit 윈도나 싱글 프로세서 머신에서 주로 사용
    • 일반적으로 사용 X
  • Parallel GC
    • SerialGC와 거의 동일하지만 병렬 처리를 지원해 더 빠르게 객체 처리 가능
    • 메모리가 크고 코어 개수가 많을 때 유리
  • CMS GC
    • SerialGC와 다르게 마크를 세 번에 나눠함
    • 다른 방식보다 메모리와 CPU를 많이 사용해 신중히 검토 후 사용
  • GI GC
    • CMS를 대체하기 위해 만들어짐
    • 힙을 여러 영역으로 나눠 GC
      • Young영역은 여러 개로 나눠 다른 콜렉터와 동일하게 스레드 정지하고 GC
      • Old영역은 백그라운드 스레드로 작동해 다른 스레드를 정지시키지 않고 GC

 

장점

  • 프로그래머가 동적으로 할당된 메모리 영역 전체를 완벽하게 관리하지 않아도 됨

 

단점

  • GC가 행동하는 시점이나 시간을 사전 예측하기 어려워 메모리가 해제되는 시점을 알 수 없음
  • 실시간 시스템에는 적합하지 않음

 

getter, setter를 사용하는 이유

  • 메서드를 통해서 접근하기 때문에, 메서드 안에서 매개변수 같이 어떤 올바르지 않은 입력에 대해 사전에 처리할 수 있게 제한하거나 조절할 수 있기 때문
  •  

 

절차 지향 프로그래밍

실행하고자 하는 절차를 정하고, 그 순차적으로 코드를 구현하는 방법으로 C언어 등이 이에 속함

장점

실행 속도가 빠름

단점

유지보수와 디버깅이 어려움

 

객체지향 프로그래밍(OOP)

실생활의 물체를 객체로 표현하고, 객체와 객체 간의 유기적인 상호작용을 통해서 코드를 구현하는 방법으로 Java, C++, C# 등이 이에 속함

장점

  • 유지보수가 편리 : 수정해야 할 부분이 클래스 내부의 메서드로 존재하기 때문에 해당 부분만 수정하면 됨
  • 코드 재사용성 용이 : 남이 만든 클래스를 가져오거나 상속을 통해 확장해 사용 가능
  • 대형 프로젝트에 적합 : 클래스 단위로 모듈화해 개발하므로 업무 분담에 유리

단점

  • 처리속도가 상대적으로 느림
  • 설계 시 많은 시간과 노력이 필요

특징

  • 추상화 : 불필요한 것을 제외하고 중요한 정보를 공통의 기능으로 묶어 정의
  • 캡슐화 : 코드를 재수정 없이 재활용하기 위해 기능과 특성 모음을 클래스에 분류
  • 상속 : 부모 클래스의 속성을 이어받아 자식 클래스에서 재정의할 수 있음
  • 다형성 : 오버 라이딩, 오버 로딩 가능

5대 원칙(SOLID)

Single Responsiblity Principle
(단일 책임 원칙, SRP)
객체는 단 하나의 책임만을 가져야함
Open Closed Principle
(개방 폐쇄 원칙, OCP)
기존의 코드를 변경하지 않고 기능을 수정하거나 추가할 수 있도록 설계해야함
Liskov Substitution Principle
(리스코프 치환 원칙, LSP)
자식클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야함
Interface Segregation Principle
(인터페이스 분리 원칙, ISP)
한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 않아야함
하나의 인터페이스보단 여러개의 구체적인 인터페이스가 나음
Dependency Inversion Principle
(의존 역전 원칙, DIP)
의존관계를 맺을 때 변화하기 쉬운것보단 변화하기 어려운 것에 의존해야함

 

정적 바인딩과 동적 바인딩

Binding
프로그램 구성요소의 성격을 결정해 주는 것 ex) 변수 데이터 타입 정하기...
함수를 만들어 컴파일하면 각각의 코드가 메모리 어딘가로 저장이 되는데, 함수를 호출하는 부분에는 그 함수가 저장된 주소 값이 저장됨

프로그램 실행 → 함수 호출 → 함수가 저장된 주소로 점프 → 함수 실행 → 원래 위치
함수를 호출하는 부분에 함수가 위치한 메모리 주소 값으로 연결시켜주는 것이 바인딩

정적 바인딩

  • 컴파일 시간에 성격이 결정됨
  • 컴파일 시간에 많은 정보가 결정되므로 실행 효율이 좋음

동적 바인딩

  • 런타임 시간에 성격이 결정됨
  • 프로그램이 실행되어야 메모리에 크기가 얼마만큼 할당되는지 알 수 있는 것을 의미
  • 런타임에 자유롭게 성격이 바뀌므로 적응성이 높음
  • 단점
    • 타입 체킹으로 인해 수행 속도 저하
    • 메모리 공간 낭비

 

Non-static과 Static

Non-static

  • 멤버는 객체마다 별도로 존재(=인스턴스 멤버)
  • 객체 생성 시에 멤버가 생성됨
  • 공유되지 않음

Static

  • 멤버는 클래스당 하나가 생성됨(=클래스 멤버)
  • 클래스 로딩 시 멤버가 생성됨
  • 동일한 클래스의 모든 객체들에 의해 공유됨
Static
클래스가 로딩될 때 메모리 공간을 할당하는데, 처음 설정된 메모리 공간이 변하지 않음을 의미
객체를 아무리 많이 만들어도 해당 변수는 하나만 존재

 

프레임워크와 라이브러리

  • 프레임워크 
    • 애플리케이션 개발 시 코드, 알고리즘, DB 연동과 같이 여러 기능을 통해 개발자가 쉽게 개발하도록 뼈대 제공
    • 실행 흐름에 대한 제어권한이 프레임워크에 있어서 프레임워크가 내 코드를 호출
    • 큰 틀을 제공하고 그 틀 안에 맞춰서 작성해야 함
    • 장점
      • 개발이 편리해 개발 시간 감소
      • 오류의 폭을 줄일 수 있음
      • 유지보수 편리
    • 단점
      • 프레임워크 의존도가 늘어나 개발 능력의 저하 우려
      • 개발자의 자유도 감소
  • 라이브러리
    • 특정 기능에 대한 도구 또는 함수들의 집합으로 개발에 필요한 것들을 모아둔 것
    • 사용자가 흐름에 대한 제어를 해서 필요할 때 호출
    • 사용할 수 있는 함수들의 모음
  •  차이점
    • 흐름에 대한 제어의 권한이 프레임워크는 제어의 역전이 적용되어 프레임워크가 권한을 가지고 있고, 라이브러리는 사용자가 흐름에 대한 제어를 하여 필요한 상황에 맞춰서 호출할 수 있음
  •  
API(Application Programming Interface)
응용프로그램에서 OS나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스

라이브러리와 API 차이
API : 컴포넌트를 사용하는 규약으로 단지 호출을 위한 수단으로 구현 로직이 없음
라이브러리 : 컴포넌트 그 자체로 구현 로직이 존재
라이브러리는 도구 그 자체이고, API는 도구를 요청하는 호출 수단이라고 볼 수 있음

 

지역 변수, 멤버 변수(클래스 변수, 인스턴스 변수)

변수가 선언된 위치에 따라 구별

public class test {
    int ins_val;	// 인스턴스 변수
    static int cla_val;		// 클래스 변수
    
    void method() {
    	int loc_val;		// 지역 변수
    }
}
  • 인스턴스 변수
    • 생성 시기 : 인스턴스가 생성될 때 생성됨
    • 각각의 인스턴스마다 고유의 값을 가져야 할 때 사용
  • 클래스 변수
    • 인스턴스 변수에 static만 붙이면 됨
    • 생성 시기 : 클래스가 로딩될 때 생성됨 (메모리에 한 번만 올라감)
    • 모든 인스턴스가 공통된 값을 공유하는 것
    • 한 클래스의 모든 인스턴스들이 공통된 값을 가져야 할 때 사용
  • 지역 변수
    • 생성 시기 : 변수 선언문이 수행되었을 때 생성됨
    • 메서드 내에 선언되어 메서드 내에서만 사용 가능
    • 메서드가 실행될 때 메모리를 할당받고 메서드가 끝나면 소멸되어 사용 불가

 

Wrapper Class

기본 자료형을 객체 타입의 자료형으로 변환할 때 주로 사용

용도

  • 객체로 저장해야 하는 경우
  • 매개변수로 객체가 요구될 경우 ex) Generic, Collection의 타입
  • 객체 간의 비교가 필요한 경우

특징

  • 산술 연산을 위한 클래스가 아니기 때문에 Immutable
  • 새로운 객체의 할당이나 참조만 가능
  • Boxing : 기본자료형에서 Wrapper Class로 변경
  • Unboxing : Wrapper Class에서 기본 자료형으로 변경
  • Autoboxing : 두 가지 타입을 자동으로 상호 변환해주는 것으로 Java에서 지원 

 

Integer과 Int

Integer

  • Wrapper 클래스(객체)
  • Unboxing을 하지 않으면 산술 연산 불가능
  • Null 값 허용
  • Collection, Null 값이 필요한 경우 사용

Int

  • Primitive 자료형
  • 산술 연산 가능
  • Null 값 비허용

 

Boxing과 Unboxing

Boxing : 기본 타입의 값을 Wrapper클래스로 바꾸는 과정

Unboxing : Wrapper 클래스를 기본 타입의 값으로 바꾸는 과정

// Boxing (int -> Integer)
Integer num1 = new Integer(num2);

// Unboxing (Integer -> int)
int num2 = num1.intValue();

 

인터페이스와 추상 클래스

공통점

  • 선언만 있고 구현 내용이 없음
  • new 연산자로 인스턴스 생성 불가능
  • 사용하기 위해서는 하위 클래스에서 확장/구현해야 함

인터페이스

  • 일종의 추상 클래스
  • 추상 메서드와 상수만을 멤버로 가짐
  • 선언 시 interface 키워드 사용, 상속 시 implements 키워드 사용
  • 상속 시 모든 메서드를 구현해야 함 (동일한 동작을 위한 강제 구현이 목적)
  • 다중 상속 가능

추상 클래스

  • 추상 메서드를 하나 이상 가진 클래스로 일반 메서드, 변수를 가질 수 있음
  • 선언 시 abstract 키워드 사용, 상속 시 extends 키워드 사용
  • 상속 시 추상 메서드만 구현 (상속을 통해 기능 확장의 목적)
  • 단일 상속만 가능
추상 메서드
선언 부만 있고 내용이 없는 메서드
꼭 필요하지만 자손마다 다르게 구현될 것으로 예상될 경우 사용
추상 클래스를 상속받는 자손 클래스에서 추상 메서드의 내용을 완성해야 함

추상 클래스와 인터페이스 차이

  • 추상 클래스는 추상 클래스를 상속받아 기능을 이용하고 확장시키는 것이 목적이고, 단일 상속만 가능
  • 인터페이스는 함수의 껍데기만 있는데 함수의 구현을 강제하기 위함이 목적이고, 그로 인해 구현 객체의 같은 동작을 보장함

 

Overriding과 Overloading

둘 다 다형성을 높여주고, 같은 이름의 다른 함수를 호출한다는 점에서 같음

Overriding

부모 클래스의 메서드와 같은 이름으로 하위 클래스에서 재정의해 사용. 함수 이름, 리턴 타입, 매개변수 모두 동일해야 함

기존의 코드를 수정하지 않고 변경된 내용을 반영할 수 있음

Overloading

같은 이름의 함수를 여러 개 정의하고, 각각의 함수의 매개변수 타입이나 개수를 다르게 정의하는 것

 

Call by Value와 Call by Reference

Call by Value(값에 의한 호출)

  • 깊은 복사라고 불림
  • 함수 인자 값을 변경해도 값만 참조하기 때문에 원래의 값에 영향을 미치지 않음
  • 하지만, 인자를 넘겨줄 때마다 메모리 공간을 할당해야 하기 때문에 메모리 공간을 차지함

Call by Reference(참조에 의한 호출)

  • 얕은 복사라고 불림
  • 함수 인자 값의 주소를 참조하기 때문에 함수 인자 값을 변경하면 직접적으로 값에 영향을 미침

 

동기와 비동기

동기(Synchronous)

  • 요청을 보내고 실행이 끝나면 다음 동작 실행
  • 여러 요청을 동시에 처리할 수 없어서 효율이 떨어짐
  • 순서에 따라 진행되어 제어가 쉬움
  • 설계가 매우 간단함

비동기(Asynchronous)

  • 요청을 보내고 처리 여부와 관계없이 다음 동작 실행
  • 결과가 나올 때까지 다른 작업을 수행할 수 있어 자원을 효율적으로 이용 가능

 

==와 equals()

둘 다 양쪽의 내용을 비교한 값을 Boolean Type으로 반환한다는 공통점을 가짐

==

  • 연산자
  • 대상의 주소 값을 비교

equals()

  • 메서드 형태
  • 대상 내용(값) 그 자체를 비교
String a = "123";
String b = a;
String c = new String("123");

// ==
System.out.printIn(a==b)	// True
System.out.printIn(a==c)	// False
System.out.printIn(b==c)	// False

// equals()
System.out.printIn(a.equals(b))	// True
System.out.printIn(a.equals(c))	// True
System.out.printIn(b.equals(c))	// True

 

반응형

'Study > Tech Interview' 카테고리의 다른 글

OS 면접 #2  (0) 2021.05.30
OS 면접 #1  (0) 2021.05.30
Data Structure 면접  (0) 2021.05.24
Algorithm - 진수 변환, 거듭 제곱, 에라토스테네스의 체  (0) 2021.05.23
Algorithm - DFS, BFS, 다익스트라, 이진 탐색  (0) 2021.05.22

댓글