본문 바로가기
Java/About Java

[Java] 객체 - 클래스

by seaweed_one 2023. 2. 6.
728x90

안녕하세요. 씨위드입니다.

오늘은 객체지향의 중요한 개념인 클래스에 대하여 알아보겠습니다.

 

클래스 

클래스는 데이터(변수)와 함수의 집합입니다.

변수는 단순하게 말하면 데이터를 저장하는 기능을 수행합니다.

그렇다면 함수는 어떤 기능을 할까요?

함수는 주로 데이터를 이용한 작업을 수행합니다.

해서 객체지향 언어에서는 데이터와 함수를 하나의 클래스에 정의해 함께 다룰 수 있도록 하였죠.

 

사용자 정의 타입 클래스

우리가 자주 사용하는 String이나 Map, ArrayList 같은 자료형도 사실은 하나의 클래스입니다.

String 클래스로 예를 들자면 클래스 내부에 문자열을 저장할 수 있는 배열과 문자열을 쉽게 다룰 수 있는 함수들이 정의되어 있죠.

 

우리도 자바의 String처럼 서로 관련된 변수를 묶어 '사용자 정의 타입'을 생성할 수 있습니다.

기본형(primitive type)은 8개뿐이지만 참조형 데이터 타입은 앞으로도 계속 만들어 질 것입니다.

기본형과 참조형에 대하여 더 궁금하신 분들은 아래 포스팅을 참고 부탁드립니다.

 

[Java] Primitive Type & Reference Type

안녕하세요. 씨위드입니다. 오늘은 자바의 데이터 타입에 대하여 포스팅해보려고 합니다. Java의 데이터 타입은 크게 기본타입(Primitive Type)과 참조타입(Reference Type)으로 나눌 수 있습니다. 각각의

seaweed-one.tistory.com

 

변수 

위에서 변수는 데이터의 저장을 담당하고 있다고 말씀드렸습니다.

데이터 저장 형태는 아래와 같이 발전해 왔는데요.

변수 -> 배열 -> 구조체 -> 클래스 

각각의 차이점에 대해 알아보겠습니다.

  • 변수 
    • 가장 기본적인 단위입니다.
    • 하나의 데이터를 저장할 수 있습니다.
  • 배열 
    • 같은 종류의 데이터들을 하나의 집합으로 저장이 가능합니다.
  • 구조체 
    •  종류에 관계없이 관련 있는 데이터를 하나의 집합으로 저장할 수 있습니다.
  • 클래스 
    • 데이터와 함수의 결합입니다.

그렇다면 변수의 종류는 무엇이 있을까요?

 

변수의 종류 

변수는 크게는 두 가지로, 작게는 세가지로 나뉩니다.

먼저 두가지로 나눠볼까요?

멤버변수와 지역변수입니다.

차이점은 바로 선언 위치입니다.

클래스 영역에 선언된 변수를 멤버변수, 멤버 변수를 제외한 나머지는 모두 지역변수입니다.

Class Seaweed{
  public static String name;
  public int age;
  
  public void eat(){
    String food = "seaweed roll";
    System.out.println(food);
  }
}

간단한 샘플 코드입니다.

위의 코드에서 멤버변수와 지역변수를 구분하실 수 있나요?

  • 멤버변수 : name, age
  • 지역변수: food

두 변수의 또 다른 차이점은 바로 소멸 시기입니다.

지역 변수는 메서드 내에서 선언되고 메서드 내에서만 사용 가능하며 메서드가 종료 시 함께 소멸됩니다.

for / while 문 안에 변수를 선언했다면 해당 블록을 벗어나서는 사용할 수 없습니다.

 

위에서 작게는 세 가지로 변수를 나눌 수도 있다고 말씀드렸습니다.

멤버변수 중에서 static으로 선언되어 있으면 클래스 변수, 그 외는 인스턴스 변수입니다.

다시 한번 분류해 볼까요?

  • 멤버변수
    • 클래스변수 : name
    • 인스턴스변수  : age
  • 지역변수 : food

그렇다면 클래스변수와 인스턴스 변수의 차이점은 무엇일까요?

바로 생성 시기입니다.

static이 붙은 클래스변수는 클래스가 메모리에 올라갈 때 생성되어 프로그램이 종료될 때까지 유지됩니다.

반면 인스턴스 변수는 인스턴스가 생성되었을 때 생성됩니다.

 

해서 클래스 변수는 클래스 내의 모든 인스턴스들이 공통된 값을 유지해야 하는 경우 선언하게 되는데요.

예시 코드에서 접근 제어자를 public으로 작성했기 때문에 Seaweed.name과 같은 형식으로 같은 애플리케이션 내 어디서나 접근할 수 있는 전역변수의 성격을 갖게 됩니다.

 

반대로 인스턴스 변수들은 독립된 저장 공간을 가지기 때문에 서로 다른 값을 저장해야 하는 경우에는 인스턴스 변수를 사용하는 것이 바람직합니다.

이해를 돕기 위해 예시 코드를 작성해 보았습니다.

Class SeaweedTest{
  public static void main(String args[]){
   Seaweed sw22 = new Seaweed();
   sw22.age = 22;
   
   Seawed sw23 = new Seaweed();
   sw23.age = 23;
  }
}

2022년에 22 살인 씨위드입니다.

전 개명을 할 생각이 없기 때문에 2023년에도 앞으로도 씨위드의 이름이 변경될 일이 없으니 static 변수로 선언하여 사용하였습니다.

 

 

메서드 

메서드는 간단하게 말해서 명령문의 집합입니다.

어떤 작업을 수행한다는 목적은 같지만 메서드에 따라 입력받는 값과 반환 값이 있을 수도 없을 수도 있습니다.

객체지향과 메서드의 가장 큰 장점은 중복 코드를 줄여 가볍고 유지보수가 편한 코드를 작성할 수 있다는 것인데요.

클린 코드 글에서 언급한 것과 같이 하나의 메서드는 하나의 기능만을 수행하도록 작성하는 것이 좋습니다.

 

메서드의 구조 

메서드는 크게 선언부와 구현부로 나뉩니다.

선언부와 구현부에 들어가는 정보는 아래와 같습니다.

선언부

  • 접근제어자
  • 리턴타입
  • 메서드명
  • 매개변수

구현부 

  • 메서드에서 수행할 동작
  • 반환값을 주고 싶다면 이곳에서 return 문을 사용할 수 있습니다.
private int getSeaweedWeight(int inputCal){
  int weight = 48;
  if(100 < inputCal){
    weight++;
  }
  retrun weight;
}

private void sleep(){
  //잠들기 위한 동작
  return;
}

예시 코드입니다.

제가 선언부에 들어가는 정보로 적은 순서대로 선언합니다.

리턴타입이 없다면 void  있다면 해당 타입을 적어주시면 됩니다.

 

그런데 sleep()  함수에서 리턴 타입이 없는데도 return을 사용한 것을 보실 수 있는데요.

사실 저부분은 생략도 가능합니다.

하지만 void 함수에는 절대로 return 이 들어갈 수 없다고 생각하시는 분들도 계시는 듯하여 예시로 작성해 보았습니다.

명시적으로 함수를 끝내는 기능을 하게 됩니다.

저는 마지막 줄에서 사용했지만 조건문과 함께 코드를 중간에 종료하는 기능을 하도록 사용할 수도 있습니다.

 

메서드의 동작

우리 가 메서드를 호출하면 어떤 일이 일어나는지 알아보겠습니다.

예시 코드를 보며 같이 이해해 보겠습니다. 씨위드를 살찌우는 로직입니다.

public static void main(String args[]){
  Seaweed sw; //1
  sw = new Seaweed; //2
    
  sw.weight = 48; //3
  sw.eat(); //4
}

1. Seaweed sw;

참조 변수를 하나 선언했습니다.

메모리에는 sw를 위한 공간이 생성됩니다.

2. sw = new Seaweed();

new 연산에 의해 Seaweed 클래스의 가 생성되었습니다.

인스턴스는 지난 포스팅에서 설명드렸죠?

이때 멤버변수는 각 자료형에 해당되는 기본값으로 초기화됩니다.

참조형 변수는 null로 그 기본타입 변수들은 해당하는 기본값으로 초기화될 것입니다.

int 변수는 기본값이 0이니 0으로 초기화 될 것입니다.

 

객체 생성 후 생성된 객체의 주소를 참조변수인 sw에 저장하게 됩니다.

주소값을 궁금해하시는 분들도 계시겠죠?

JVM은 객체의 주소가 고정되어 있지 않습니다.

가비지 컬렉터가 객체의 위치를 바꾸기 때문에 주소값이 의미가 없다고 합니다. 

또 보안문제로 직접 접근을 하는 것을 권유하지 않는다고 합니다.

 

3. sw.weight = 48; → 꿈의 몸무게죠?

참조변수 sw에 저장된 주소에는 Seaweed 클래스 인스턴스의 멤버변수인 weight 이 존재할 것입니다.

그곳에 48을 저장합니다.

이번에는 함수를 한 번 호출해 보겠습니다.

 

4. sw.eat();

참조변수가 참조 중인 Seaweed 인스턴스의 eat() 메서드를 호출했습니다.

해당 메서드는 저장되어 있는 weight의 값을 48 → 49로 변경합니다.

 

그럼 아래와 같은 코드는 어떨까요?

public static void main(args[]){
  Seaweed sw = new Seaweed();
  sw.name = "one";
  sw.height = 160;
  sw.weight = 48;
  
  Seaweed sw2 = new Seaweed();
  sw2 = sw;
}

 sw2의 생성 절차는 위와 같으니 생략하겠습니다.

결과적으로 아래와 같은 그림이 나오게 됩니다.

간단한 로직이지만 메서드의 동작 방식을 설명해 보았습니다.

해당 변수들이 어떤 메모리 공간에 생성되는지가 궁금하시다면 저의 JVM 포스팅을 참고해 주세요.

 

[Java] Java Memory

이번 포스팅에서는 자바의 메모리 영역에 대하여 알아보겠습니다. 본격적으로 알아보기에 앞서 왜 메모리 영역을 알아야 하는 걸까요? 자바에는 가비지 컬렉터(Garbage Collector)가 존재하여 사용

seaweed-one.tistory.com

 

728x90

'Java > About Java' 카테고리의 다른 글

[Java] Immutable Object  (0) 2023.02.14
[Java] 얕은 복사 & 깊은 복사 & 방어적 복사  (0) 2023.02.13
[Java] 생성자  (2) 2023.01.31
[Java] Java Memory Leak  (0) 2023.01.11
[Java] Primitive Type & Reference Type  (0) 2023.01.09