한화시스템 BEYOND SW 7주차 회고록

김채우·2025년 11월 3일

새롭게 배운 것

25.10.27

1. 다형성

1.1 정의

하나의 인스턴스가 여러가지 타입을 가질 수 있는 것

  • 하나의 타입으로 여러 타입의 인스턴스 처리 가능
  • 하나의 메소드 호출로 객체별로 각기 다른 방법으로 동작 가능
  • 객체지향 프로그래밍의 3대 특징 중 하나

1.2 장점

  1. 여러 타입의 객체를 하나의 타입으로 관리 가능하기 때문에 유지보수성과 생산성 증가
  2. 상속 기반이기 때문에 상속 관계에 있는 모든 객체는 동일한 메시지 수신 가능
    • 동일한 메시지를 수신받아 처리 내용을 객체별로 다르게 할 수 있음
  3. 확장성이 좋은 코드 작성 가능
  4. 결합도를 낮춰서 유지보수성 증가

1.3. 동적 바인딩

컴파일 당시에는 해당 타입의 메소드와 연결되어 있다가 런타임 시 실제 해당 인스턴스가 메소드로 바인딩이 바뀌어 동작하는 것

1.3.1. 동적 바인딩의 조건

  • 상속 관계를 가지는 부모 자식 클래스에 오버라이딩된 메소드를 호출해야 함

1.4. 업캐스팅 / 다운캐스팅

  • 상속 관계에 있지만 오버라이딩 한 것이 아닌 후손 객체가 고유하게 가지는 확장된 기능을 사용하기 위해서는 실제 인스턴스 타입으로 다운캐스팅 필요
  • 클래스 형변환은 상위 타입 형변환과 하위 타입 형변환이 있음
  • 상위 타입 형변환은 묵시적으로 일어나며 하위 타입 형변환은 명시적이어야 함

1.5. Instanceof 연산자

클래스 형변환의 경우 런타임시 존재하는 타입과 형변환하려는 타입이 일치하지 않는 경우 ClassCastException 발생
따라서 런타임 시 안전한 형변환을 하기 위해 instanceof 연산자 이용 가능
instanceof 연산자는 레퍼런스 변수가 실제로 어떤 클래스 타입의 인스턴스인지 확인해 true / false 반환

If(레퍼런스 변수 instanceof 클래스 타입) {
		// true일 때 처리할 내용, 해당 클래스 타입으로 down-casting할 것
}

Car car = new Sonata();
if(car instanceof Sonata) {
		((Sonata) car).moveSonata();
} else if(car instanceof Avante) {
		((Avante) car).moveAvante();
} else if(car instanceof Grandure) {
		((Grandure) car).moveGrandure();
}

2. 추상 클래스와 인터페이스

2.1 추상 클래스

메소드의 기능이 없고 메소드의 헤더부만 존재하는 불완전한 메소드인 추상 메소드를 0개 이상 포함하는 클래스
스스로 자신의 생성자를 활용한 인스턴스의 생성 불가능

  • 따라서 추상 클래스는 불완전한 클래스
  • 추상 클래스는 상속을 활용해 하위 클래스 타입의 인스턴스를 이용해 인스턴스를 생성해야 함
  • 추상 메소드를 하나라도 포함하면 반드시 추상 클래스가 되어야 함

2.1.2. 추상 클래스의 사용 이유

  • 추상 클래스는 다형성 적용을 위한 부모 타입 역할을 할 수 있음
  • 추상 메소드를 포함한 추상 클래스는 추상 메소드를 통해 자식 클래스에 오버라이딩에 대한 강제성 부여 가능
  • 필수 기능을 정의해 일관된 인터페이스(동일 기능) 를 제공함에 있어 도움
  • 추상 클래스를 상속받는 자식 클래스는 반드시 추상 메소드를 오버라이딩 해야함

2.2. 인터페이스

추상 메소드와 상수 필드만 가질 수 있는 클래스의 변형체
implement 키워드를 사용하며 클래스 입장에서 구현한다 라는 표현 사용

interface TestInter {
		
		// 모든 필드는 public static final만 가능하다.
		public static final PI1 = 3.1415;

		// public static final을 생략해도 자동으로 작성된다.(생략 가능)
    PI2 = 3.14;

    // 기본적으로 메소드는 public abstract여야 한다.
		public abstract void method1();

    // public abstract를 생략해도 자동으로 작성된다.(생략 가능)
    void method2();
}
class Person extends SuperClass implements Instinct, Serializable {

		@Override
		public void eating(String food) {
				System.out.println("사람은 " + food + "를 요리하고 식기를 활용해 음식을 먹는다.");
    }
}

2.2.1. 인터페이스 사용 이유

공유를 목적으로 하는 상수(public static final 필드)를 기반으로 모든 기능을 공통화(public abstract 메소드)해 강제성을 부여할 목적으로 사용

  • 자바의 단일 상속이라는 단점을 극복하기 위해 사용되기도 함
  • 모든 클래스는 하나의 부모 클래스 외에도 여러 개의 인터페이스 구현 가능
public class Application implements InterOne, InterTwo {
		
		@Override
		public void interOneMethod() {}

		@Override
		public void interTwoMethod() {}
}

2.3. 추상 클래스 vs 인터페이스

2.3.1. 차이점

구분추상 클래스인터페이스
상속 가능 범위단일 상속다중 상속
키워드extends 사용implements 사용
추상 메소드 개수abstract 메소드 0개 이상모든 메소드는 abstract
abstract 키워드 명시명시적 사용묵시적으로 abstract

2.3.2. 공통점

구분추상 클래스인터페이스
자체 인스턴스 생성생성 불가생성 불가
다형성 적용 시 상위 타입
활용 가능 유무가능가능

25.10.28

1. Object

최상위 부모 클래스

  • 모든 클래스는 Object 클래스를 상속하고 있으므로 Object 클래스 내부의 메소드 사용 가능
  • Object 클래스가 가지는 메소드를 오버라이딩해 사용 가능

1.1. Object 주요 메소드

메소드설명
boolean equals(Object obj)전달 받은 객체와 같은지 여부를 반환한다.(동일하면 true, 다르면 false)
int hashCode()객체의 해시 코드를 반환한다.
String toString()객체의 정보를 문자열로 반환한다.

1.2. Object 활용

1.2.1. toString()

  • toString() 메소드는 인스턴스의 정보를 문자열로 반환
  • 반환되는 문자열은 클래스 이름과 구분자 '@' 사용, 그 뒤로 16진수 해시코드 붙임
  • 사용 시 해시코드가 아닌 인스턴스 안의 값을 확인하고 싶다면 오버라이딩해 사용

1.2.2. equals()

  • 매개변수로 전달받은 인스턴스와 == 연산해 true, false로 반환
  • 동일한 인스턴스인지를 비교하는 기능
  • 동일 객체
    - 주소가 동일한 인스턴스
  • 동등 객체
    - 주소가 달라도 필드값이 동일한 객체
  • 동등 객체를 동일 객체로 취급해 비교하고 싶은 경우
    - equals() 메소드를 오버라이딩
    - 각 필드가 동일한 값을 가지는지 확인
    - 모든 필드값이 같은 값을 가지는 경우 true, 그렇지 않은 경우 false 반환

1.2.3. hashCode()

  • 해시코드는 객체를 식별하는 값
  • Object의 hashCode() 메소드는 객체의 메모리 주소값을 이용해 해시코드를 만들어 반환
  • Object 클래스의 명세서에 따르면 equals() 메소드를 재정의 하는 경우 반드시 hashCode() 메소드도 재정의 해야함
  • hashCode()를 재정의하지 않으면 같은 값을 갖는 동등 객체는 같은 해시코드 값을 가져야 한다는 규약에 위반
    - 강제성은 없지만 규약대로 작성하는 것이 좋음

2. String

문자열을 나타내는 자료형

  • 문자열 관련 작업을 할 때 유용하게 사용할 수 있는 다양한 메소드 포함
  • String 인스턴스는 한 번 생성되면 그 값을 읽기만 가능하고 변경할 수 없음
    • 불변 객체(immutable object)
  • 덧셈 연산자를 이용해 문자열을 결합하는 경우 기존 문자열이 변경되는 것이 아닌 문자열이 합쳐진 새로운 String 인스턴스 탄생

2.1. 주요 메소드

메소드설명
charAt()해당 문자열의 특정 인덱스에 해당하는 문자를 반환한다.
인덱스는 0부터 시작하는 숫자 체계를 의미하며 인덱스를 벗어난 정수를 인자로 전달하는 경우에는
IndexOutOfBoundsException이 발생한다.
compareTo()인자로 전달된 문자열과 사전 순으로 비교를 하여 두 문자열이 같다면 0 을 반환, 인자로 전달된 문자열보다 작으면 음수를,
크면 양수를 반환한다.
단, 이 메소드는 대소문자를 구분하여 비교한다.
compareToIgnoreCase()대소문자를 구분하지 않고 비교한다
concat()문자열에 인자로 전달된 문자열을 합치기해서 새로운 문자열을 반환한다.
원본 문자열에는 영향을 주지 않는다.
indexOf()문자열에서 특정 문자를 탐색하여 처음 일치하는 인덱스 위치를 정수형으로 반환한다.
단, 일치하는 문자가 없는 경우 -1을 반환한다.
lastIndexOf()문자열 탐색을 뒤에서부터 하고 처음 일치하는 위치의 인덱스를 반환한다.
단, 일치하는 문자가 없는 경우 -1을 반환한다.
trim()문자열의 앞 뒤에 공백을 제거한 문자열을 반환한다.
toLowerCase()모든 문자를 소문자로 변환시킨다. 원본에는 영향을 주지 않는다.
toUpperCase()모든 문자를 대문자로 변환시킨다. 원본에는 영향을 주지 않는다.
substring()문자열의 일부분을 잘라내어 새로운 문자열을 반환한다. 원본에 영향을 주지 않는다.
replace()문자열에서 대체할 문자열로 기존 문자열을 변경해서 반환한다. 원본에 영향을 주지 않는다.
length()문자열의 길이를 정수형으로 반환한다.
isEmpty()문자열의 길이가 0이면 true를 반환, 아니면 false를 반환한다. 길이가 0인 문자열은 null과는 다르다.
split()정규표현식을 이용하여 문자열을 분리한다.

3. String Builder & String Buffer

3.1. 개요

문자열 처리 시 가장 많이 사용하게 되는 클래스가 String, StringBuffer, StringBuilder

  • String은 불변이기 때문에 이를 해결하기 위해 StringBuilder, StringBuffer 등장
  • StringBuffer는 Thread safe하지만 StringBuilder는 그렇지 않음
  • StringBuffer는 synchronized 키워드가 선언되어 있기 때문에 멀티스레드에서 안전하지만 속도는 StringBuilder에 비해 느림
StringStringBuilderStringBuffer
modifiableXOO
thread safeOXO
synchronizedXXO
performance빠름빠름느림

4. Wrapper

래퍼 클래스는 기본 타입의 데이터를 인스턴스화 해야하는 경우에 사용

4.1. 사용하는 경우

  • 특정 메소드가 매개변수로 객체 타입만 요구하게 되면 기본 타입의 데이터를 먼저 인스턴스로 변환 후 넘겨줘야 함
  • 이 때 8가지의 기본 타입 데이터를 인스턴스화할 수 있도록 하는 클래스가 래퍼 클래스

4.2. 종류

기본 타입래퍼 클래스
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

4.3. 박싱과 언박싱

4.3.1. 박싱

  • 기본 타입을 래퍼 클래스의 인스턴스로 인스턴스화

4.3.2. 언박싱

  • 래퍼 클래스 타입의 인스턴스를 기본 타입으로 변경

4.4. 오토 박싱과 오토 언박싱

  • JDK 1.5부터 박싱과 언박싱에 필요한 상황에서 자바 컴파일러가 이를 자동으로 처리
  • 자동화된 박싱과 언박싱을 오토 박싱, 오토 언박싱이라 함

5. Time 패키지

5.1. Time 패키지에 들어가기 전

  • Java에서 기본적으로 사용한 날짜 API는 java.util.Datejava.util.Calendar
  • 불편하기에 JDK 8에서 개선된 날짜와 시간 API인 java.time 패키지 제공

5.2. Date와 Calendar 클래스

5.2.1. Date 클래스

JDK 1.0부터 날짜를 가볍게 취급하기 위한 java.util에 속한 클래스

  • 지금은 생성자를 비롯해 대부분의 메소드가 Deprecated됨
  • Deprecated
    - 향후 버전이 업데이트되며 사라지게 될 기능이나 가급적이면 사용을 권장하지 않는다는 의미
    - 하위 버전 호환성 때문에 한 번에 제거된 것은 아니고 남겨두었기에 사용은 가능

5.2.2. Calendar 클래스

JDK 1.1.부터 제공되는 시간과 날짜에 관한 처리를 담당하는 클래스

  • 단점
    1. Calendar 인스턴스는 불변객체가 아니기 때문에 값 수정 가능
    - set 메소드를 통해 값을 변경할 수 있기 때문에 어느 흐름 중간에 값이 바뀐다고 하면 알아채기 힘들고 사이드 이펙트 발생 가능성 높음
    - 멀티 스레드 환경에서 안전하지 않음
    2. 윤초(leap second) 고려하지 않음
    3. Calendar 클래스는 월을 나타낼 때 0부터 11월까지로 표시
    - 하지만 일주일을 나타내는 숫자는 1부터 시작
    - 일관성 부족

5.2.3. Date와 Calendar 간 변환

public static void main(String[] args) {

    /* Calendar 를 Date 로 변환 */
    Calendar calendar = Calendar.getInstance();

    System.out.println("calendar = " + calendar);
    
    Date date = new Date(calendar.getTimeInMillis());

    System.out.println("date = " + date);
} 
public static void main(String[] args) {

    /* Date 를 Calendar 로 변환 */
    Date date = new Date();

    System.out.println("date = " + date);
    
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

    System.out.println("calendar = " + calendar);
}

5.3. Time 패키지

Date, Calendar의 단점을 해소하기 위해 등장

  • Date와 Calendar와 다르게 불변
  • 값을 변경하면 기존 객체가 변경되는 것이 아니라 새로운 객체 반환
  • 불변하기 때문에 멀티스레드 환경에서도 안전

5.3.1. 하위 패키지

패키지설명
java.time날짜와 시간 관련 클래스들을 제공한다
java.time.chronoISO-8601 에 정의된 외에 달력 시스템을 위한 클래스들을 제공한다
java.time.format날짜와 시간 파싱과 형식화 관련 클래스들을 제공한다
java.time.temporal날짜와 시간의 필드와 단위 관련 클래스들을 제공한다
java.time.zone시간대 관련된 클래스들을 제공한다

5.3.2. 핵심 클래스

클래스명설명
LocalTime시간 관련 작업할 때 사용하는 클래스. LocalTime 객체는 두 개의 정적 메소드를 통해 반환 받을 수 있다.
LocalDate날짜 관련 작업할 때 사용하는 클래스. LocalDate 객체도 두 개의 정적 메소드로 반환 받는다.
LocalDateTime시간과 날짜를 함께 작업해야할 때 사용하는 클래스
ZonedDateTime시간대(Time Zone) 을 활용한 작업해야할 때 사용하는 클래스

25.10.29

1. 예외처리

1.1. 개요

오류: 시스템 상에서 프로그램에 심각한 문제가 발생해 실행중인 프로그램이 종료되는 것
예외: 실행중인 프로그램을 종료시키는 것이 일반적이지만 발생할 수 있는 상황을 개발자가 미리 예측하고 처리할 수 있는 미약한 오류

  • 예외는 개발자가 적절히 처리해 코드의 흐름을 컨트롤할 수 있음

1.2. 예외 처리를 사용하는 이유

오류나 예외는 사용자에게 좋지 않은 사용 경험 제공

  • 미리 예측하고 컨트롤 할 수 있는 예외를 처리함으로써 프로그램이 예상치 못 한 상황에 봉착하지 않도록 코드의 안정성과 신뢰성을 높여 이를 미연에 방지하거나 의도한 방향으로 컨트롤 가능
  • 개발 시에도 디버깅을 용이하게 해 예외가 발생한 원인과 위치도 쉽게 파악 가능

1.3. 예외 클래스의 종류

1.3.1. 예외 클래스의 계층구조

  • 오류와 예외는 모두 Throwable 상속
  • 예외의 최상위 클래스는 Exception 클래스
  • Unchecked Exception 계열은 기본적으로 이미 처리되어 있고 실행중인 프로그램이 종료되게 작성되어 있음
    - 강제성이 없음
  • Checked Exception 계열은 반드시 예외 처리를 해야 하고 하지 않으면 컴파일 에러 발생
    - 강제성 있음
  • RuntimeException 타입의 예외들은 런타임 시점에 해당 예외 클래스 타입의 Exception 발생

1.3.2. RuntimeException 후손 클래스

  • ArithmeticException
    - 0으로 나누는 경우 발생
	int dividend = 3;
	System.out.println(dividend / 0);
  • ArrayIndexOutOfBoundsException
    - 배열의 index 범위를 넘어서 참조하는 경우 발생
	int[] intArr = new int[0];
	System.out.println(intArr[1]);
  • **NullPointerException
    - 인스턴스가 참조되지 않는 상태로 인스턴스에 접근하는 경우 발생
	int[] intArr = null;
	System.out.println(intArr[0]);
  • ClassCaseException
    - 형 변환(Case 연산자 사용) 시 자료형에 있을 때 발생
	Object obj = new String("hello");
	int num = (Integer)obj;
  • NegativeArraySizeException
    - 배열 크기를 음수로 지정한 경우 발생
int[] intArr = new int[-1];

1.4. 예외처리 방법

1.4.1. throws로 위임

Exception이 발생하는 메소드 또는 생성자를 호출한 상위 메소드에게 처리 위임

1.4.2. try-catch(try-catch-finally)로 처리

발생한 Exception을 직접 처리

  • try 블럭
    예외가 발생할 가능성이 있는 코드를 포함해 작성하는 블럭
  • catch 블럭
    try 블럭에서 예외 발생 시 해당 예외 타입에 대한 처리를 기술하는 블럭
    여러 개의 catch 블럭을 이어서 사용 가능하며 상위 타입의 예외를 처리하는 catch 블럭이 아래 쪽에 위치해야 함
  • finally 블럭
    예외 발생 여부와 상관 없이 꼭 실행되어 처리해야 할 코드가 있으면 작성하는 블록
    주로 java.io나 java.sql 패키지의 메소드 처리 시 자원 반납을 위해 사용

1.5. 오버라이딩 시 예외 발생 가능 범위

  • 상속 시 오버라이딩하는 메소드는 부모 클래스의 원본 메소드보다 더 상위 타입의 예외를 발생시키면 안 됨

1.6. try-with-resource 구문

  • 자바 7 버전에서 추가된 기능
  • 입출력에서 사용되는 스트림의 자원 반납(close())를 finally 블럭을 사용하지 않고 용이하게 처리하기 위해 도입된 문법
try (BufferedReader in = new BufferedReader(new FileReader("test.dat"));){
	
	String s;
	
	while((s = in.readLine()) != null){
		System.out.println(s);
	}

} catch (FileNotFoundException/* | EOFException*/ e) {
	e.printStackTrace();

} catch (IOException e) {
	e.printStackTrace();
}

25.10.30

1. 입출력

IO란 Input과 Output의 약자

  • 컴퓨터 내부 도는 외부 장치와 프로그램 간의 데이터 연동을 위한 자바 라이브러리
  • 단방향 데이터 송수신을 위해 스트림을 활용해 데이터를 서로 주고 받음

1.1. 스트림

입출력 장치에서 데이터를 읽고 쓰기 위한 단방향 통로

  • 각 장치마다 연결할 수 있는 스트림이 존재하며 바이트 단위 처리와 문자 단위 처리를 위한 스트림 등이 존재
  • 스트림은 기본적으로 1바이트 단위의 데이터만 지나감
  • 주고 받는 데이터의 기본 단위가 1바이트이므로 한 방향만 처릭가 가능
  • 입력 스트림과 출력 스트림을 따로 구성해야 함
  • 2,3바이트를 사용하는 언어도 있기 때문에 크기는 인코딩 방식에 따라 정해짐
  • 2,3바이트 단위를 구분해 입출력하기 위해서는 문자 단위를 처리할 수 있는 스트림을 활용해야 함

1.2. 입출력을 사용하는 이유

사용자로부터 입력을 받거나 화면이나 스피커로 출력


2. 파일 입출력

2.1. 파일 클래스(File Class)

파일 시스템의 파일을 다루기 위한 클래스

  • 파일의 크기나 속성, 이름 등의 정보 확인 가능
  • 파일 생성 및 삭제 기능 등을 제공
File file = new File("file path");
File file = new File("C:/data/childDir/grandChildDir/fileTest.txt");$
  • 파일/디렉토리 메소드
리턴 타입메소드설명
booleancreateNewFile()새로운 파일 생성
booleanmkdir()새로운 디렉토리 생성
booleanmkdirs()경로 상에 없는 모든 디렉토리 생성
booleandelete()파일 또는 디렉토리 삭제
booleancanExecute()실행할 수 있는 파일인지 여부
booleancanRead()읽을 수 있는 파일인지 여부
booleancanWrite()수정 및 저장할 수 있는 파일인지 여부
StringgetName()파일 이름 리턴
StringgetParent()부모 디렉토리 리턴
FilegetParentFile()부모 디렉토리를 File객체로 생성 후 리턴
StringgetPath()전체 경로 리턴
booleanisDirectory()디렉토리인지 여부
booleanisFile()파일인지 여부
booleanisHidden()숨김 파일인지 여부
longlastModified()마지막 수정 날짜 및 시간 리턴
longlength()파일 크기 리턴

2.2. 파일 입출력 관련 기반 스트림 종류

2.2.1. 바이트 단위(영어, 숫자, 특수기호 사용 시)

  • InputStream
  • OutputStream

2.2.2. 문자 단위(한글까지 사용 시)

  • Reader
  • Writer

2.3. 파일 입출력 관련 보조 스트림의 종류

스트림의 기능을 향상시키거나 새로운 기능을 추가하기 위해 사용

  • 보조 스트림만으로는 데이터를 주고 받는 대상에 대한 처리를 하는 것이 아님
  • 따라서 입출력 처리가 불가능
  • 기반 스트림에 추가로 적용되어야 함

2.3.1. 입출력 성능 향상

  • BufferedInputStream
  • BufferedOutputStream
  • 입출력 속도 향상 및 한 줄씩 출력 및 입력 관련 메소드 제공

2.3.2. 형변환 보조 스트림

  • InputStreamReader
  • OutputStreamWriter
  • 인코딩 방식을 고려한 한글 깨짐 방지를 위해 고려 가능

2.3.3. 기본 자료형 데이터 입출력

  • DataInputStream
  • DataOutputStream
  • 기본 자료형 및 문자열 관련 타입에 따른 메소드 제공

2.3.4. 객체 자료형 데이터 입출력

  • ObjectInputStream
  • ObjectOutputStream
  • 객체 단위 입출력

3. Generics

데이터 타입의 일반화

  • 제네릭스를 활용하는 제네릭 클래스는 제네릭 타입(T, E, K, V)을 활용해 하나의 클래스로 해당 제네릭 타입에 변화를 줘 제네릭 클래스의 인스턴스를 다양한 타입을 지닌 인스턴스로 활용 가능
public class GenericTest<T> {

	private T value;
	
	public T getValue() {
		return value;
	}
	
	public void setValue(T value) {
		this.value = value;
	}
}

// 제네릭 클래스의 T(타입)에 해당하는 부분이 모두 Integer로  변환된다.
GenericTest<Integer> gt = new GenericTest<Integer>();

3.1. 사용 이유

하나의 클래스만 작성해도 여러 타입의 필드 값을 가진 클래스로 변형해 다룰 수 있기 때문에 구현의 편의성

  • 제네릭 적용 클래스는 타입을 명확히 알고 쓰기 때문에 해당 제네릭 클래스의 필드 타입이나 메소드의 매개변수나 반환형을 알고 사용하여 자료형의 안정성이 높다

3.2. 와일드카드

제네릭 클래스의 인스턴스를 유연하게 활용하기 위한 문법

  • 메소드의 매개변수로 받을 시 타입을 원하는 만큼으로 제한
  • 불특정한 제네릭 클래스 타입을 조금 더 활용
<?>: 모든 타입을 허용하는 와일드카드
<? extends T>: T 타입 또는 T의 하위 타입을 허용하는 와일드카드
<? super T>: T 타입 또는 T의 상위 타입을 허용하는 와일드카드

4. 컬렉션

4.1. 개요

많은 데이터들을 효과적으로 처리할 수 있는 방법을 제공하는 클래스들의 집합

  • JDK 1.2부터 정립
  • Collection의 인터페이스는 List, Set, Queue로 크게 3가지 상위 인터페이스로 분류
  • List, Set, Queue는 Collection 인터페이스를 상속받지만 구조 상의 이유로 Map은 따로 구현

4.1.1. Collection 사용 이유

  1. 일관된 API
    • Collection에서 제공하는 규격화된 메소드를 사용함으로써 일관된 사용과 유지보수 가능
  2. 프로그래밍 비용 감소
    • 이미 제공된 자료구조를 활용하는 것으로 low-level의 알고리즘을 고민할 시간과 노력 감소
  3. 프로그래밍 속도 및 품질 향상
    • 필요한 자료구조를 사용함으로써 프로그래밍의 속도 뿐만 아니라 기동 속도, 품질 향상 기대

4.1.2. Collection 주요 인터페이스 특징

인터페이스설명구현 클래스
List순서가 있는 데이터의 집합으로, 데이터의 중복을 허용한다.ArrayList, LinkedList, Stack, Queue, Vector
Set순서가 없는 데이터의 집합으로, 데이터 중복 허용하지 않는다.HashSet, LinkedHashSet, TreeSet
Map<K, V>키와 값이 쌍를 이루어 구성되는 데이터 집합으로 순서가 없다.
키의 중복은 허용되지 않지만, 값의 중복은 허용된다.HashMap, TreeMap, Properties

4.2. List

순서가 있는 데이터의 집합
데이터의 중복 저장 허용

  • 종류: ArrayList, LinkedList, Vector, Stack

4.2.1. List 특징

  • List 인터페이스를 구현한 모든 클래스는 저장 순서 유지
  • List 계열의 클래스는 중복 저장 허용

4.2.2. ArrayList

동적 배열 구현

  • 특징
    • 인스턴스를 생성하게 되면 내부적으로 10칸짜리 배열을 생성해 관리
    • 배열의 단점을 보완하기 위해 만들어졌기 때문에 크기 변경, 요소 추가/삭제/정렬 기능들을 메소드로 제공
    • 자동적으로 수행되는 것이지 속도가 빠른 것은 아님
    • 스레드 간 동기화 지원 x
    • 다수의 스레드가 동시에 접근해 데이터를 조작할 경우 데이터 훼손 발생 가능
    • 인덱스로 데이터에 접근할 수 있기 때문에 조회 기능적으로 뛰어남

4.2.3. LinkedList

ArrayList 클래스가 배열과 유사하게 데이터를 저장함으로써 발생하는 단점 보완

  • LinkedList 특징
    • 저장되는 데이터들이 연속된 공간에 저장되지 않고 각 데이터를 링크를 연결해 구성
    • 데이터의 삽입, 삭제가 빈번한 경우 연결되는 링크 정보만 수정하면 되기 때문에 ArrayList보다 더 적합
      • 스택, 큐, 양방향 큐 등을 구성하기 용이
  • LinkedList 종류
    • 단일 연결 리스트
      • 저장한 요소가 순서를 유지하지 않고 저장
      • 요소들 사이를 링크로 연결해 연결된 리스트 형태인 것 처럼 구성
        - 요소의 저장과 삭제 시 다음 요소를 가리키는 참조 링크만 변경하면 되기 때문에 요소의 저장과 삭제가 빈번한 경우 ArrayList보다 성능적으로 우수
    • 이중 연결 리스트
      • 단일 연결 리스트는 다음 요소만 링크하는 반면 이중 연결 리스트는 이전 요소도 링크해 이전 요소로 접근하기 쉽게 고안된 자료구조

Keep

현재 스터디 팀에 들어가 스프링에 대한 스터디를 진행하고 있다. 또한 그 팀에서 이번주부터 보험사 페이지를 만드는 사이드 프로젝트를 시작했다. 지금은 요구사항 정의서를 먼저 작성하고 있다. 보험이라는 도메인이 익숙하지는 않기에 검색을 정말 많이 하고 나서야 조금씩 진전이 있었다. 차주에 각자 작성한 요구사항 정의서를 합쳐 서로 형식 등을 맞출 예정이다.

스프링 교재는 "토비의 스프링"을 공부하고 있다. 이번 주차가 첫 발표였다. 총 5명의 팀원이 각자 공부하고 깃허브에 정리한 내용을 올려 월요일에 무작위로 한 명을 뽑아 발표한다. 이러한 방식으로 하기에 더욱 신경써 준비를 했다. 아쉽게도 나는 발표자가 아니었지만 발표를 듣고 질문을 함으로써 더욱 이해를 잘 할 수 있었다.

Problem

이번에 배운 것 중 가장 어렵고 서툴렀던 부분이 예외 부분이다. 이전에 학교에서 개인이나 팀 프로젝트를 할 때 개발 중에 에러가 발생하면 당연히 그 에러를 해결했다. 하지만 지금 와서 생각해 보면 그것은 단순히 개발자의 입장에서의 해결이었다. 사용자가 어디서 어떻게 상호작용을 했을 때 에러가 발생하는지 알고 있기 때문에 상식 선에서만 에러가 발생하지 않도록 하고 '그렇게 까지는 안 하겠지'라는 안일한 생각으로 개발을 이어나갔다.

하지만 이번에 배운 예외는 내가 과거에 다룬 예외와는 느낌이 달랐다. 이전에는 나에게 예외란 보기 싫은 것, 반드시 고쳐서 콘솔에도 화면에도 띄워서는 안 되는 것이었다. 하지만 이번에 배우고 실습에서 활용해본 예외는 하나의 뛰어난 기능이자 도구였다. 해당 예외가 발생했을 때 적절한 로직을 작성해 프로그램이 의도치 않게 종료되는 것을 막고 사용자에게 정상적인 답변을 출력한다.

  • 가장 새롭게 느껴진 부분은 아래와 같다.
    int[] iArr = {1, 2, 3, 4}
    int count = 0;
    
    while (true) {
    	System.out.println(iArr[i]);
    	count++;
    }
    
    try {
    	System.out.println("프로그램 종료");
    } catch (IndexOutOfBoundsException e) {
    	System.out.println("프로그램 종료");
    }

    while문의 조건을 true, 즉 무한 반복으로 설정한다. 이 때 i의 값은 계속해서 증가하기 때문에 i의 값이 4가 되면 예외가 발생한다. 보통은 for문을 사용해 이러한 예외를 막는다. 하지만 오히려 이러한 예외가 발생했을 시 실행할 적절한 로직을 구성해 기능으로서 이용한다.

Try

이번 주 금요일에는 PCCP에 응시했다. 이번이 두 번째인데 아주 심각할 정도로 못 풀었다. 지금까지는 애써 바쁘니까, 할 게 많으니까라는 이유로 못 본 척 하고 있었지만 코딩 테스트는 사실 필수적이라는 사실을 직시하고 받아들여야 할 때이다. 매일 몇 문제씩이라도 백준에서 푸는 습관을 들여야 한다. 기초적인 부분부터라도 괜찮으니 시간을 조금씩 들여서 다름 시험에서는 다른 결과를 보고 싶다.

profile
예비 백엔드 개발자

0개의 댓글