[Java 풀스택 과정 강의] 2월 4일

부트캠프 일지/Java 풀스택 과정 강의
2026.02.09

 

2월 4일의 일지. 2월 5일에 java를 완료하고 SQL 설치했다.

 

Object 타입

이 Object 타입에 대해서 이해하려면 java 구조에서 object가 차지하는 위치를 알아야 한다. java.lang.Object는 모든 클래스의 최상위 부모다. 이에 따라 Object는 자동상속 받고, 이 Object에 따른 메서드도 자동 상속 받게 된다. 앞에서 말했던 toString 같은 경우도 Object 에 따라오는 메서드이다. Object에서 오는 메서드는 다음과 같다.

 

메서드 설명
toString() 객체를 문자열로 반환한다. 기본은 해시값을 반환한다.
equals(Object obj) 두 객체가 “같은지” 비교한다. 기본은 참조값에 대해 비교한다.
hashCode() 해시값을 반환한다.
getClass() 이 객체의 Class 객체를 반환한다.
clone() 복제 한다.
wait() / notify() / notifyAll() 스레드 동기화에 사용

 

이에 따라 어떤 참조 타입이든 Object 변수에 담을 수 있기 때문에, 여러 타입을 한 종류의 컨테이너에 넣고 싶을 때 사용했다. Object box class를 선언해서 사용했다. 

 

class Box {
    private Object object;

    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
}

Box box = new Box();
box.set("문자열");
box.set(123);
Object v = box.get();

 

그러나 이 방법에는 몇 가지 한계점이 있었다. 컴파일 당시 타입 검사가 불가능하고, 꺼낼 때마다 캐스팅(강제 형변환)을 하는 등의 번거로움이 많았다. 즉, 강제 형변환을 잘못하면 런타임 에러가 터진다는 것이다. 이런 수요와 불편함에 따라 Java 5에서 제네릭Generic이 업데이트 되었다.

 

 

제네릭(Generic)

제네릭은 클래스나 메서드를 만들 때, 구체적인 타입을 나중에 정할 수 있게 해준다. 일종의 요술 자판기 같은 것이라, 인스턴스를 쓰거나 만들 때 타입을 정해주면 된다.

 

코드를 보자.

// T라는 타입은 후에 지정
class Box<T> {
    private T value;
    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

// 쓸 때 T를 String으로 정하여 꺼낸다(캐스팅 없음)
Box<String> box = new Box<>();
box.set("hello");
String s = box.get();

 

T,E,K,V 같은 타입 변수를 사용하여 저장하고, 사용할 때 사용할 타입을 꺾쇠 안에 넣어 사용한다. 참고로 정수의 경우 Integer를 사용해야하는데, 보다시피 참조 타입을 넣어야 하기 때문이다(String의 경우 본래부터 참조타입). 그렇다고 하여도 int처럼 사용할 수 있도록 자동형변환 되므로 별도 캐스팅이 필요하진 않다.

 

참고로 new Box부분에 String이나 Integer를 사용해도 되지만, 보통은 <> 상태로 비워둔다. 이 Generic은 후에 설명할 ArrayList에서도 사용된다.

 

 

제네릭 메서드

메서드에 제네릭 타입 변수를 붙이면 제네릭 메서드라고 한다. 클래스가 제네릭이 아니어도 사용할 수 있다.

public static <T> T echo(T t) {
    return t;
}

String s = echo("hello");
Integer i = echo(100);

 

 

멀티타입 제네릭 메서드

타입변수에 복수 타입을 사용할 수 있으면 멀티타입 제네릭 메서드라고 한다.

 

public static <K, V> K getKey(K key, V value) {
    return key;
}

String key = getKey("이름", 20);   // "이름"
Integer num = getKey(1, "일");     // 1

 

 

이런 식으로 제네릭 메서드는 컴파일러 시점에서 T(를 포함한 제네릭 변수)의 타입을 정해줄 수 있다.

 

 

ArrayList

ArrayList는 컬렉션 중 하나이다. ArrayList는 import java.util.ArrayList; 형태로 import하여 사용한다. 배열 형태로서 여러가지 타입을 담기 때문에 제네릭과 같이 사용되는 경우가 많다.

new ArrayList<>(); 형식으로 만들 수 있고, 일반적으로 List 형태의 변수가 자주 사용된다.

 

import java.util.ArrayList;
import java.util.List;

public class ArrayList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
    }
}

 

 

List

List는 인터페이스이다. import java.util.List; 형태로 자주 사용된다. ArrayList 외에 Linked List에서도 자주 사용되는데, 이 덕분에 구현을 확실하게 하지 않음으로써 구현을 바꾸기 쉬워진다.

 

 

List 메서드

  • List.add(참조변수); 형태로 List에 추가할 수 있다.
  • List.get(i); 형태로 i 위치의 내용을 불러올 수 있다.
  • List.size(); 형태로 배열의 길이를 알 수 있다.
  • List.remove(i); 형태로 i 위치의 내용을 삭제할 수 있다. 이때 뒤에 있는 요소는 앞당겨진다.

리스트 메서드를 적용하면 이렇게 된다.

import java.util.ArrayList;
import java.util.List;

public class ArrayListSample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("사과");
        list.add("바나나");
        list.add("포도");

        System.out.println(list.get(0));   // 사과
        System.out.println(list.size());  // 3

        list.remove(1);                    // 바나나 삭제
        System.out.println(list);          // [사과, 포도]

        for (String s : list) {
            System.out.println(s);
        }
    }
}

 

 

 

LinkedList

Linked List도 보통 List를 사용한다.

둘의 차이로는 내부 구조의 차이가 있다. ArrayList는 하나의 배열 덩어리인데 반해, LinkedList는 노드들이 앞뒤 주소로만 연결된 상태다. 비유를 하자면 기차와 돌로 된 징검다리 같은 형태다. ArrayList는 유기적으로 붙어있는 것에 반해 LinkedList는 다음 값의 참조 주소만 알고 있는 셈이다. 이에 따라 둘의 속도가 다른데, 기본적으로는 ArrayList가 더 빠르다.

그렇다면 왜 LinkedList를 쓰느냐, 중간 삽입 및 삭제 시에는 LinkedList가 더 빠르기 때문이다. 참조를 하기 때문에 빠르게 참조 주소만 바로 삭제하고 다시 연결하면 되기 때문에, ArrayList보다 더 쉽고 빠르다.

 

 

2월 4일의 수업은 여기까지였다.