자바 문법 종합반(3)

하늘·2025년 2월 26일

Spring 부트캠프

목록 보기
13/18

2-1 클래스의 객체

클래스(class)란? - 객체를 만들 때 필요한 청사진

  • 청사진(설계도)
  • 클래스의 첫글자는 대문자

객체(object)란?

  • 컴퓨터, 계산기, 자동차 같은 사물들이 객체
  • 어떤 개념이나 논리 같은 것들도 객체가 될 수 있음
  • 덧셈,뺄셈 등 눈에 보이지 않은 것들도 무형의 객체가 될 수 있음
  • 클래스가 준비되어 있으면 클래스를 기준으로 여러 객체들을 만들어 낼 수 있음

Person.class

  • 클래스는 객체를 만들기 위한 설계도
  • Person 클래스는 사람 객체를 만들기 위한 설계도
  • 객체를 만들 때 new라는 키워드를 사용
  • 객체를 만드는 과정을 인스턴스화 라고 표현
  • 인스턴스화가 되면 Java 메모리 상에 객체가 만들어짐

클래스 구조(생성, 생성자, 기능)

  • 클래스 구조는 1. 속성, 2. 생성자, 3. 기능 부분으로 나누어짐
  • 속생기라고 외우면 편함

속성

  • null은 데이터가 비어있다고 의미

생성자(Constructor) - 조립설명서

  • 객체를 만들 때 사용
  • 객체를 어떻게 만들지 정의해 놓는 것(조립설명서)
  • 생성자가 없으면 클래스를 객체화 시킬 수 없음 (조립 불가)
  • Person() {} = 기본생성자는 class 생성시 만들어지지만 우리 눈에 보이지 않음
  • 생성자를 정의한 순간 기본 생성자는 사라짐

생성자의 특징

  • 클래스와 이름이 같음
  • 반환 타입이 존재하지 않음
  • 여러개가 존재할 수 있음

this 키워드

  • this는 객체 자신을 가리키는 키워드
  • 현재 실행중인 객체를 의미

기능

  • 기능은 메서드로 표현
  • 상상하는 모든 기능 구현 가능
    → ex) 자기소개, 더하기, 걷기 기능 등
  • 클래스와 관련된 기능을 작성하는 것이 좋음
  • 메서드를 활용하는 것이 객체의 기능을 활용하는 것

게터, 세터(Getter, Setter)


게터(Getter) – 속성을 가져오는 기능
세터(Setter) – 속성을 설정해주는 기능

2-2 JVM 메모리 영역

Java 메모리 구조는 크게 3가지로 나눔

  • Method Area ( 도서관처럼 책들이 정리되어있는 책장 같은 느낌이라 생각하면 됨)
  • Stack Area (접시 쌓기구조, 프로그램 실행 흐름에 따라 호출된 매서드들이 실행 순서대로 쌓이기도 하고 빠져나가기도 함, 접시처럼 위에부분부터 빠져나감 아래부터 뺄 수 없음 )
  • Heap Area(객체가 저장되는 공간, 객체는 크기가 다 다름)

Method(static) 이해하기

  • 프로그램이 실행되면 작성했던 모든 파일의 데이터가 Method(static)영역에 저장
  • 프로그램 실행 시점에 한번만 저장
  • Method 영역에 저장된 데이터는 프로그램 전체에서 공용으로 활용 가능

Heap영역 이해하기

  • new 키워드로 생성된 객체는 Heap 영역에 저장
  • Stack 영역의 변수가 Heap 영역의 객체를 참조 ( 화살표 → 로 가리키고 있는 모습)

Stack 영역 이해하기

  • 메서드가 호출될 때마다 Stack 영역에 메모리가 쌓임
  • 접시를 쌓듯이 LIFO-후입선출 구조
  • 메서드가 시작되면 추가되고 메서드가 종료되면 사라지는 구조
  • 특정 메서드가 실행되면 해당 메서드의 정보의 변수가 Stack에 저장되고 메서드 실행이 끝나면 그 메모리는 자동으로 제거
  • 메서드 내에 선언된 지역변수들이 저장되는 공간 → 변수에 객체가 담기면 객체의 주소값이 저장

2-3 레퍼클래스(기본형 참조형)

래퍼클래스(Wrapper Class)란?

  • 기본자료형을 객체로 감싸는 클래스

기본형(Prinitive Type)의 종류

참조형(Reference Type)

  • 변수에 객체가 담기면 해당 변수를 참조형변수라고 함
  • 참조형 변수는 데이터가 저장된 메모리 주소를 가르킴
    → Heap 메모리 주소
  • 객체 데이터는 Heap 영역에 저장되어 있기 때문
  • 객체, 배열 등이 참조형에 속함
  • 빨간네모박스안에 있는 값이 메모리에 주소값

래퍼클래스도 객체

  • 래퍼클래스가 담겨 있는 변수도 참조형 변수
  • 출력시 메모리 주소값이 나오지 않음
  • 내부적으로 toString()이 오버라이딩 되어 있어 메모리 주소값이 아닌 숫자가 출력 됨

왜 래퍼클래스를 사용할까?

  • 기본형은 객체처럼 속성, 기능을 가질 수 없음
  • 객체는 기능 제공 가능
  • 기본형을 감싼 객체를 만들어 기능을 제공하면 편리하게 데이터처리 가능

래퍼클래스 코드

오토방식 VS 언박싱

  • 래퍼클래스 ↔ 기본형으로 형변환이 자주 일어남
  • Java에서는 형변환 과정을 자동으로 지원

오토박싱(Auto-boxing)

  • 기본형 → 래퍼형으로 변환하는 과정을 오토박싱
  • Integer는 참조형(객체)이지만 기본형 int 값을 직접 대입 가능
  • 내부적으로 컴파이러가 자동으로 Integer.valueOf(10)을 호출하여 객체를 생성하기 때문

오토 언박싱

  • 래퍼형 → 기본형으로 변환하는 과정
  • num은 Integer 객체(참조형변수)지만 기본형 int 변수에 대입 가능
  • 내부적으로 컴파일러가 자동으로 num.intValue()를 호출하여 기본형으로 변환하기 때문

기본형과 래퍼형 성능 비교

  • 래퍼형은 내부적으로 데이터를 감싸고 있기 때문에 연산시 불리
  • 객체에서 기본형 값을 꺼내서 연산하는 추가작업이 발생하기 때문
  • 추가 작업 때문에 기본형보다 래퍼클래스는 연산 속도가 느림
  • 빠른 작업이 필요한 경우 기본형을 직접 활용하는 것이 좋음

2-4 : static – 클래스가 공유하는 공간

Static 란

  • static 키워드는 모든 객체가 함께 사용하는 변수나 메서드(기능)를 만들 때 사용
  • 객체(인스턴스)를 만들지 않아도 클래스 이름만으로 바로 사용 가능
  • 모든 객체가 같은 값을 공유
    → 공용게시판이라고 생각하면 이해하기 쉬움
  • static 변수와 메서드는 한 번만 생성되고 Method Area(메서드 영역)에 저장

Static 활용

  • static 키워드는 변수, 메서드에 붙일 수 있음
  • static 키워드로 선언된 변수와 메서드는 MethodArea에 저장
  • 각 개체(인스턴스)는 클래스 영역에 저장된 데이터 활용 가능
  • 객체 생성안하고 클래스 레벨에 접근해서 바로 사용 가능
  • 프로그램 실행시점에 클래스에 대한 정보가 메서드 영역에 저장되서 바로 활용 가능

인스턴스 멤버(인스턴스 변수 + 인스턴스 메서드)

  • 객체를 만들때마다 생성되는 변수와 메서드 임
  • 객체(인스턴스)를 생성한 후에만 사용 가능
  • 각 객체가 개별적으로 값을 가짐(공유되지는 않음)
  • 인스턴스는 Heap 영역에 위치

인스턴스 변수란

  • 객체가 생성될 때마다 따로 만들어지는 변수
  • 객체를 생성한 후 접근 할 수 있음
  • name변수는 각 객체마다 별도로 저장

인스턴스 메서드란

  • 객체의 속성을 활용하는 메서드
  • 객체가 생성된 후에만 사용 가능

인스턴스 멤버 실습

  • 인스턴스 멤버, 변수는 객체를 생성하기 전에 활용 불가
  • 인스턴스 메서드와 변수는 각 객체가 고유로 가지고 있는 기능임

클래스 멤버 (클래스 변수 + 클래스 메서드)

  • 클래스 자체에 속하는 변수와 메서드를 의미
  • static 키워드에 사용해서 선언
  • 해당 클래스로 만들어진 객체가 공유해서 사용할 수 있음
  • 클래스가 로드될 때 Method Area에 적재
  • 객체 생성 없이 사용 가능

클래스 변수란

  • 클래스가 로드될 때 한 번만 생성
  • 모든 객체가 공유하는 변수
  • Heap이 아니라 Method Area에 저장
  • 객체를 만들지 않아도 클래스명.변수명으로 접근가능

클래스 메서드란

  • 클래스에 속하는 메서드
  • 객체 없이 사용 가능
  • 클래스 변수만 사용 가능, 인스턴스 변수는 사용 불가

클래스 멤버 실습

Static 사용시 주의사항

  • 클래스 변수 사용시 주의 사항
    → Static은 공유가 필요한 곳에 사용해야함
  • Static 메서드에서 인스턴스 변수에 접근
    → Static 메서드에서는 인스턴스변수에 접근 불가
    → 인스턴스 멤버를 사용하기 위해서는 먼저 객체가 생성되어야 함
    → 객체 생성없이 사용할 수 없음, 접근도 당연히 불가

2-5 final – 변하지 않는 값

final의 용도

  1. 변수에서 final
  • 변수에 final을 붙이면 변수를 한 번만 설정 가능
  1. 클래스에서 final
  • final로 선언된 클래스는 상속할 수 없음
  1. 메서드에서 final
  • final로 선언된 메서드는 오버라이딩 할 수 없음
  • 자식입장에서 부모에 기능을 다시 재정의 할 수 없음

상수(Constant)

  • 변하지 않고 항상 일정한 값을 갖는 수
  • Java에서 상수는 대문자로 표현하는 것이 관례
  • 프로그램 실행중에 절대 변경되서는 안되기 때문에 static final 키워드를 사용해 선언
  • static으로 선언된 변수는 프로그램 시작시 한 번만 초기화되고 모든 인스턴스에서 같은 값을 공유

대표적인 상수 예시 : PI(원주율)

  • 원의 넓이, 둘레를 구할 때 공통으로 사용되는 값(변경되면 안됨)

static으로 선언하는 이유(복습)

  • 보통 상수는 여러 곳에서 값을 공유해 쓰일 목적으로 활용
  • 인스턴스 변수를 static 없이 선언할 경우 인스턴스마다 PI 값이 중복 저장

static없이 선언할 경우

  • 인스턴스를 생성할 때 class기반으로 생성된 각 인스턴스들은 c1 c2 c3에 값을 가지게 됨
  • 중복된 값을 사용하는건 공용이 아니여서 올바른 상수 활용법이 아님

상수 활용 법

불변객체(Immutable Object)

  • 불변객체는 내부 상태를 변경할 수 없는 객체
  • final을 속성(property,field)에 활용
  • 세터(setter)없이 설계
  • 변경이 필요한 경우 새로운 객체를 만들어야 함
    → ex) String, Integer, 래퍼클래스 등

잘못된 불변객체 사용

  • final은 참조 변경을 막지만 내부상태 변경은 막지 않음
public class Circle {

    final static double PI = 3.14159; // ✅ 직접 만든 원주율 상수
    double radius; // ⚠️ final 로 선언되어 있지 않기 때문에 외부에서 변경 가능

    Circle(double radius)  {
        this.radius = radius;
    }
}

final Circle c1 = new Circle(2);
c1 = new Circle(3); // ❌ final은 변수 c1이 한 번 참조한 객체는 다른 객체로 변경될 수 없음을 의미함 (참조 불변)

// 하지만 객체 내부의 속성 값은 변경 가능 (불변 객체가 아님)
c1.radius = 3; // ⚠️ 내부 상태 변경 가능 (객체 자체가 불변이 아님)

올바른 불변 객체 활용
- 속성을 final로 서언해 줌

public final class Circle {

    final static double PI = 3.14159; 
    final double radius; // ✅ final 로 선언해서 값이 변경되지 않도록 합니다.

    Circle(double radius)  {
        this.radius = radius;
    }
}

불변 객체의 값이 변경이 필요한 경우

  • 불변성을 유지하면서 값을 변경하는 효과를 어을 때 활용
  • 기존 객체의 상태를 직접 변경할 수 없기 때문에 새로운 객체를 생성
  • 생성자를 새로 호출하거나 아래의 기능을 활용
public final class Circle {
    public static final double PI = 3.14159;
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    // ✅ 반지름이 다른 새로운 Circle 생성 (불변 객체 유지)
    public Circle changeRadius(double newRadius) {
        return new Circle(newRadius); // 생성자 호출: 기존 객체 변경 X, 새 객체 생성
    }
}

2-6 인터페이스 – 표준화의 시작

인터페이스(interface)란

  • 설계 표준
  • 클래스가 따라야할 최소한의 공동 규칙을 정의하는 역할

인터페이스 사용하는 이유

  • 모든 설계에 표준이 있는 이유와 같음
  • 개발자마다 서로 다른 방식으로 메서드를 만든다면 일관성이 깨질 수 있음
  • 인터페이스를 활용해서 최소한의 규격을 정의
  • 세부 구현은 각 클래스에 맡김
  • 일관성을 유지하면서 클래스가 고유한 특색을 확장할 수 있도록 도움

자동차 예시

  • LuxuryCar 와 SpeedCar 모두 자동차를 구현하고 있습니다.
  • LuxuryCar 를 이용하는 경우 move() 메서드로 주행할 수있지만
  • SpeedCar 를 이용하는 경우 drive() 메서드를 활용해 주행해야합니다.

인터페이스 적용

  • 모든 클래스가 지켜야 할 최소한의 규칙을 정의
  • 클래스에서 implements 키워드로 인터페이스를 활용할 수 있음
  • 인터페이스를 구현한 클래스를 구현체라고 함

인터페이스 실습

  • LuxuryCar, SpeedCar
  • Main, interface

인터페이스의 다양한 기능

  • 인터페이스 다중구현
  • 인터페이스 다중 상속

인터페이스 다중구현(multi-implementation)

  • implements 키워드로 다수의 인터페이스를 구현 가능
  • 한 개의 클래스가 여러 인터페이스(animal, flyable)를 구현한 경우 다중구현이라고 함

인터페이스 다중상속(multi-inheritance)

  • extends 키워드로 상속을 구현할 수 있음
// 1. 기본 인터페이스: 동물의 기본 기능
interface Animal {
    void eat();
}

// 2. 추가 인터페이스: 나는 기능
interface Flyable {
    void fly();
}

// 3. ✅ 다중 상속새로운 인터페이스: 동물 + 나는 기능
interface FlyableAnimal extends Animal, Flyable {
    void land();  // 추가 기능
}

// 4. 새 클래스 (FlyableAnimal을 구현)
class Bird implements FlyableAnimal {

    public void eat() {
        System.out.println("새가 먹이를 먹습니다.");
    }

    public void fly() {
        System.out.println("새가 하늘을 납니다.");
    }

    public void land() {
        System.out.println("새가 착륙합니다.");
    }
}

인터페이스에 변수를 선언하는 경우

  • 변수 선언시 형식에 관계 없이 자동으로 상수로 선언
  • public static final로 선언
  • static으로 선언되기 때문에 구현체(인터페이스를 구현한 클래스) 없이도 활용 가능
  • 인터페이스는 표준의 역할임으로 변수선언은 최소화하는 것이 좋음

4개의 댓글

comment-user-thumbnail
2025년 2월 26일

잘 봤습니다만 초심을 찾아주세요..

답글 달기
comment-user-thumbnail
2025년 2월 26일

저도 하늘님처럼 TMI 잘 써보고 싶네요 ㅠㅠ.

답글 달기
comment-user-thumbnail
2025년 2월 26일

4이차 초심을 찾아주세요....ㅠ

답글 달기
comment-user-thumbnail
2025년 2월 26일

초심 어디가셨죠...? 기대하겠습니다

답글 달기