본문 바로가기

코딩 국비 학원/Do it! 자바 프로그래밍 입문

[Do it! 자바 프로그래밍 입문]함수, 메서드, 클래스와 인스턴스

22.12.04 배운 내용 정리
(함수, 메서드, 클래스와 인스턴스)

 

함수

 

함수 = 하나의 기능을 수행하는 일련의 코드

ex. 두 숫자를 더하는 세 가지 경우의 수가 있다고 가정했을 때 세 가지 경우를 각각 프로그램으로 구현하는 데,

사실 세 경우 모두 '두 수를 더해서 결과 값을 보여 준다'는 기능임.

이런 경우에 더하기 기능을 수행하는 코드를 묶어서 '더하기 함수'로 만들 수 있고,

더하기 기능이 필요할 때마다 이 함수를 불러서 연산 할 수 있음.

 

이처럼 함수는 어떤 기능을 수행하도록 미리 구현해 놓고 필요할 때마다 호출하여 사용할 수 있음

 

함수의 입력과 반환

 

함수 = 이름이 있고 입력 값과 결과 값을 가짐.

함수에 이름을 붙일 때는 의미를 알 수 있는 단어를 사용하는 것이 좋음(ex. 더하는 함수의 경우 add)

함수의 입력으로 받는 변수(ex. num1, num2)를 '매개변수'라고 하며 두 수를 더한 결과 값을 result 변수에 저장하여 돌려주는 것을 '결과를 반환한다'고 함. 그리고 이렇게 함수를 수행한 후 결과로 되돌려 주는 값인 result를 '반환 값'이라고 부름.

 

함수 정의하기

 

ex. 더하기 함수를 실제 코드로 작성

int add(int num1, int num2) {      //int = 함수 반환형, add = 함수 이름, int num1 & int num2 = 매개변수

     int result;

     result = num1 + num2;

     return result;                         //return = return 예약어

}

 

이렇게 함수가 하는 일을 코드로 구현하는 것을 '함수로 정의한다'라고 함

 

함수 이름 add

함수 반환 형인 int 바로 다음 위치가 함수 이름을 적는 부분임.

함수 이름은 변수 이름처럼 프로그래머가 임의로 만들면 되는데,

함수 기능과 관련 있게 만들어야 나중에 호출하거나 이해하기 좋음

 

매개변수 num1, num2

add 함수는 두 깂을 더하는 일을 하며, 덧셈을 수행하기 위해서는 먼저 함수에 두 값이 입력되어야 함.

이 두 값은 함수를 호출할 때 괄호 안의 자료형에 맞게 함수에 전달됨.

함수는 넘겨받은 값으로 덧셈을 수행함. 이렇게 함수 내부에서 사용할 괄호 안에 변수를 매개변수라고 함

 

※ 매개변수가 필요 없는 함수

int getTenTotal( ) {

    int i;

    int total = 0;

    for(i = 1; i <= 10; i++) {

      total += i;

   }

   return total;        //1부터 10까지 더한 값을 반환

}

 

→ 위 getTenTotal( ) 함수의 기능은 1부터 10까지 더한 합을 반환 하는 것임.

따라서 함수에 전달할 값이 굳이 필요하지 않음.

이런 경우에 함수는 매개변수가 필요 없고 함수를 수행한 결과 값만 있게 됨

 

return 예약어와 반환형

add( ) 함수를 수행한 후 결과 값은 변수 result에 저장됨.

result에 저장된 결과 값은 함수를 호출했을 때 반환되는 값이므로 '반환 값'이라고도 부름.

return은 '이 함수의 결과 값을 반환합니다'를 뜻하는 예약어임. 즉 return 예약어를 사용하여 result 값을 반환하는 것임.

반환 값의 자료형을 반환형이라고 하며 위 함수에서 변수 result의 반환형은 정수형이므로

함수 반환형 위치에 int를 적은 것임

 

※ 반환 값이 없는 함수

void printGreeting(String name) {

     System.out.println(name + "님 안녕하세요");  //전달 받은 매개변수 name을 사용하여 인사말 출력

     return;    //반환 값 없음

}

 

※ return 예약어는 함수 수행을 끝내고 프로그램 흐름 중에서 호출한 곳으로 다시 되돌아갈 때도 사용 가능

void divide(int num1, int num2) {

   if(num2 == 0) {

     System.out.println("나누는 수는 0이 될 수 없습니다.");

     return;    //함수 수행 종료

   }

   else {

     int result = num1 / num2;

     System.out.println(num1 + "/" + num2 + "=" + result + "입니다.");

   }

}

 

위 divide( )함수는 두 수를 매개변수로 전달받아서 나눗셈을 한 후 몫을 출력하는 함수임.

근데 만약 나누는 수가 0이라면 수행해선 안됨 → 이 경우에는 함수 수행을 종료하는 예약어 return 사용

함수 수행을 종료하는 목적이므로 return 뒤에 반환값을 적지 않아도 됨

 

함수 호출하고 값 반환하기

 

함수를 사용하는 것을 '함수를 호출한다'라고 함

 

※ add( ) 함수 구현

add( ) 함수는 두 개의 매개변수에 int형 값을 전달받아 두 수의 합을 돌려주며, 결과 값이 정수이기 때문에 반환형이 int형임

 

add( ) 구현하고 호출하기

 

※ 매개변수 살펴보기

위 코딩에서 add( ) 함수를 호출할 때 넘긴 변수(num1, num2)와 add( )함수를 구현하는 부분에서 사용한(n1, n2)는

전혀 서로 상관이 없음.

num1, num2는 main( ) 함수의 변수이고, add(num1,num2)로 사용하면 add( ) 함수에 두 값을 넘겨줄 수 있음.

매개변수 n1, n2는 실제 함수로 넘어온 두 값을 받아주는 역할을 함.

다시 말해 n1, n2는 add( ) 함수에서 선언한 새로운 변수임.

따라서 함수를 호출할 때 사용하는 변수 이름과 호출되는 함수에서 사용하는 변수는 서로 다른 변수이므로

이름이 같아도 되고 달라도 상관 없음.

 

※ 사칙 연산 함수 완성하기

더하기 SUM, 빼기 IMSUB, 곱하기 PRODUCT,  나누기 QUOTIENT

 

 

함수 호출과 스택 메모리

 

함수를 호출하면 그 함수만을 위한 메모리 공간이 할당되는데, 이 메모리 공간을 스택이라고 부름

스택은 자료가 상자처럼 쌓이는 자료구조를 말함

스택은 마지막에 추가된 자료부터 순서대로 꺼내서 사용할 수 있으며 LIFO(last in first out, 후입선출) 구조라고 부름

 

※ add( ) 함수를 호출하면서 메모리를 생성하는 과정

 

 

※ add( ) 함수 수행이 끝나고 함수에 할당했던 메모리 공간을 해제하는 과정

 

 

프로그램에서 여러 함수를 사용하는 경우, 함수를 호출한 순서대로 메모리 공간이 만들어지고,

맨 마지막에 호출한 함수부터 반환됨(LIFO). 따라서 메모리 공간도 맨 마지막에 추가된 것부터 스택에서 사라짐.

A( ) → B( ) → C( ) 함수의 순서로 호출했다면 C( ) → B( ) → A( ) 순서로 반환되고 스택 메모리도 이 순서대로 소멸됨.

 

그리고 그림에서 보듯 main( ) 함수에서 사용하는 num1, num2 변수와 add( ) 함수에서 사용하는 n1, n2 변수는

서로 다른 메모리 공간을 사용하므로 이름이 같든 다르든 상관없음.

이렇게 함수 내부에서만 사용하는 변수를 지역 변수라고 하며, 지역 변수는 스택 메모리에 생성

 

함수의 장점

 

① 함수를 사용하면 기능을 나누어 코드를 효율적으로 구현할 수 있음

ex. 계산기를 구현하려면 먼저 숫자를 입력받고, 사칙 연산을 한 후 결과 값을 출력함.

이 과정을 구현하는 코드를 main( ) 함수 안에 한꺼번에 작성할 수도 있겠지만 덧셈, 뺄셈, 곱셈, 나눗셈으로

기능을 나누어 각 연산을 수행하는 함수를 여러 개 만든 후 main( ) 함수에서 필요할 때마다 각 함수를 호출할 수도 있음.

이렇게 기능을 분리해서 구현하면 프로그램 코드의 가독성이 좋아짐.

 

② 기능별로 함수를 구현해 놓으면 같은 기능을 매번 코드로 만들지 않고 그 기능의 함수를 호출하면 되니까 편리함.

그리고 중복되는 코드를 막을 수도 있음.

 

③ 프로그램을 실행할 때 생긴 오류를 수정하는 디버깅 작업을 할 때 편리함.

하나의 기능이 하나의 함수로 구현되어 있기 때문에 오류가 난 기능만 찾아서 수정하면 되기 때문.

 

클래스 기능을 구현하는 메서드

 

메서드 = 자바 프로그램의 클래스 내부에서 사용하는 멤버 함수로, 메서드는 멤버 변수를 사용하여 클래스를 구현함.

즉 메서드는 함수에 객체 지향 개념이 포함된 용어로 이해하면 됨.

함수의 스택 메모리 사용 방법과 함수의 장점 등도 모두 메서드에 동일하게 적용됨

 

※ 메서드 구현하기

 

메서드 이름은 해당 클래스를 사용하는 코드의 입장에서 짓는 것이 좋음.

 

학생 이름 반환 메서드

 

ex. Student 클래스를 사용하는 A 클래스가 있다고 할 때 A 클래스에서 학생 이름(studentName)을 가져오는(get) 기능을

제공하는 메서드 이름은 getStudentName으로 지음.

이 메서드의 반환 값은 StudentName인데 StudentName 자료형이 String이므로 반환형도 String임.

 

학생 이름 부여 메서드 추가

 

학생 이름을 멤버 변수에 대입하는 setStudentName( ) 메서드는 Student 클래스를 사용하는 다른 코드에서 학생 이름을

새로 지정하거나 바꾸어 줌. 이는 StudentName 값을 지정하는(set) 기능을 제공하는 것임.

이 메서드는 이름을 전달받아 지정하는 것이기 때문에 매개변수 name이 필요함.

매개변수 name을 멤버 변수 StudentName에 대입하면 학생 이름이 지정되며,

반환 값은 없으므로 반환형은 void로 지정

 


 

클래스 사용과 main 함수

 

 

Student 클래스는 멤버 변수와 메서드로 구성되어 있음.

멤버 변수는 클래스 속성을 나타내고 메서드는 멤버 변수를 이용하여 클래스 기능을 구현함

 

※ 클래스를 직접 사용해서 결과 값 출력하기

 

프로그램을 시작하는 main( ) 함수

클래스를 사용하여 프로그램을 실행하려면 먼저 main( ) 함수를 알아야 함.

main( ) 함수는 자바 가상 머신(JVM)이 프로그램을 시작하기 위해 호출하는 함수로,

클래스 내부에 만들지만, 클래스의 메서드는 아님

 

main( ) 함수에서 클래스를 사용하는 방법은 두 가지가 있음.

하나는 우리가 만든 클래스 내부에 main( ) 함수를 만드는 것이고,

또 하나는 외부에 테스트용 클래스를 만들어 사용하는 것임

 

Student 클래스에 main( ) 함수 추가하기

 

 

위와 같이 클래스 내부에 main( ) 함수를 만들면 이 클래스가 프로그램의 시작 클래스가 됨.

클래스가 제대로 수행되는지 알아보기 위해 이렇게 클래스 내부에 main( ) 함수를 만들고 직접 실행 가능함.

그런데 프로젝트를 수행하거나 소프트웨어를 개발할 때 모든 클래스에 main( ) 함수가 있는 것은 아님

 

③ main( ) 함수를 포함한 실행 클래스 따로 만들기

 

 

클래스가 같은 패키지에 있으면 패키지 이름이 동일함(ex. classpart).

이런 경우는 위와 같이 코드를 작성해도 문제가 되지 않음.

그런데 만약 패키지가 다르다면 import문을 사용해서 함께 사용하기를 원하는 클래스를 불러와야 함.

 

※ 클래스 이름이 같아도 패키지가 다르면 다른 클래스

Student라는 같은 이름의 두 클래스를 하나의 패키지에 구현하면 오류가 발생함(같은 이름 클래스 존재)

하지만 패키지가 다르면 문제가 되지 않음. 그 이유는 aaa 패키지 하위의 Student 클래스의 실제 이름은 aaa.Student이고, bbb 패키지 하위의 Student 클래스의 실제 이름은 bbb.Student이기 때문.

이것을 클래스의 전체 이름이라고 함. 따라서 패키지가 다르면 클래스 이름이 같아도 다른 클래스임.

 

new 예약어로 클래스 생성하기

 

※ 클래스를 생성하는 코드

클래스형 변수 이름 = new 생성자;

 

자바에서 클래스를 생성할 때는 new 예약어를 사용하고 이어서 생성자를 써줌.

클래스 자료형 변수를 선언하고 new 예약어로 생성자를 호출하여 대입하면 새로운 클래스가 생성됨.

새로운 클래스가 생성된다는 것은 클래스를 실제 사용할 수 있도록 메모리 공간(힙 메모리)을 할당 받는다는 뜻임.

이렇게 실제로 사용할 수 있도록 생성된 클래스를 '인스턴스'라고 하며,

이러한 인스턴스를 가리키는 클래스형 변수를 '참조 변수'라고 함.

 

ex. Student studentAhn = new Student( );

위 코드는 Student 클래스 자료형으로 studentAhn 변수를 선언하고

new Student( );로 student 클래스를 생성하여 studentAhn에 대입한다는 뜻임.

이때 studentAhn을 참조 변수라고 하고, 이 변수가 생성된 인스턴스를 가리킴.

 

인스턴스와 참조 변수

 

객체, 클래스, 인스턴스

객체 = 의사나 행위가 미치는 대상, 생성된 클래스의 인스턴스

클래스 = 객체를 코드로 구현한 것

인스턴스 = 클래스가 메모리 공간에 생성된 상태

 

클래스의 생성자를 호출하면 인스턴스가 만들어지는데 이러한 인스턴스는 여러 개 생성 가능함.

클래스는 하나이지만, 이 클래스로부터 여러 개의 각각 다른 인스턴스를 생성할 수 있는 것임.

ex. 학교에서 학생이란 추상어는 뜻이 하나이지만, 그 학교에 다니는 학생 개개인은 여러 명인 것과 같음.

각 학생은 이름, 학번, 학년 등이 다름. 즉 클래스라는 틀에서 인스턴스를 여러개 만들어 프로그램을 구현하는 것임.

 

인스턴스 여러 개 생성하기

서로 다른 인스턴스(student1, student2)가 두 개 생성됨

 

 

참조 변수 사용하기

참조 변수를 사용하면 인스턴스의 멤버 변수와 메서드를 참조하여 사용할 수 있는데 이때 도트(.) 연산자를 사용함.

 

ex. studentAhn참조 변수로 studentName 멤버 변수에 이름을 저장하고 getStudentName( ) 메서드를 사용하는 코드

studentAhn.studentName = "안연수";                                //멤버 변수 사용

System.out.println(studentAhn.getStudentName( ));         //메서드 사용

 

인스턴스와 힙 메모리

 

힙 메모리(heap memory) = 변수를 저장할 공간이 필요할 때 사용하는 메모리,

즉 클래스 생성자를 하나 호출하면 인스턴스가 힙 메모리에 생기는 것임.

힙(heap) =  프로그램에서 사용하는 동적 메모리 공간

일반적으로 프로그램은 스택, 힙, 데이터 이렇게 세 영역을 사용하는데, 객체가 생성될 때 사용하는 공간이 힙임.

힙은 동적으로 할당되며 사용이 끝나면 메모리를 해제해 주어야 함.

C나 C++ 언어에서는 프로그래머가 직접 메모리를 해제해야 하지만,

자바에서는 가비지 컬렉터가 자동으로 메모리를 해제해 줌.

 

ex. Student studentAhn = new Student( );

위와 같이 생성된 클래스를 studentAhn 변수에 대입하면, 인스터스가 저장된 메모리를 studentAhn 변수가 가리킴.

여기서 studentAhn 변수는 지역 변수이며 스택 메모리에 생성되고, 인스턴스는 힙 메모리에 생성됨.

지역 변수 studentAhn에 생성된 인스턴스를 대입하는 것은

studentAhn에 인스턴스가 생성된 힙 메모리의 주소를 대입한다는 것과 같은 뜻임.

 

ex. Student student1 = new Student( );

      Student student2 = new Student( );

생성된 두 인스턴스는 각각 다른 메모리 공간을 차지함.

따라서 student1.studentName과 student2.studentName은 서로 다른 값을 가지게 됨.

클래스가 생성될 때마다 인스턴스는 다른 메모리 공간을 차지함. 다시 말하면 멤버 변수를 저장하는 공간이

매번 따로 생긴다는 의미임. 이런 이유 때문에 클래스에 선언한 멤버 변수를 다른 말로 '인스턴스 변수'라고도 부름.

 

※ 참조 변수와 참조 값

참조 변수는 힙 메모리에 생성된 인스턴스를 가리킴

 

 

힙 메모리에 생성된 인스턴스의 메모리 주소는 참조 변수에 저장됨.

위 코딩에 출력내용을 확인해보면 클래스 이름@주소값 으로 나오는데,

여기에 나오는 주소값은 다른 말로 해시 코드 값이라고도 함.

이 값은 자바 가상 머신에서 객체가 생성되었을 때 생성된 객체에 할당하는 가상 주소 값임.

따라서 student1 변수를 사용하여 student1 인스턴스를 참조할 수 있으며,

이때 student1을 참조 변수, 주소 값을 참조 값이라고 함.

 

※ 용어 정리

용어 설명
객체 객체 지향 프로그램의 대상, 생성된 인스턴스
클래스 객체를 프로그래밍하기 위해 코드로 만든 상태
인스턴스 클래스 메모리에 생성된 상태
맴버 변수 클래스의 속성, 특성
메서드 멤버 변수를 이용하여 클래스의 기능을 구현
참조 변수 메모리에 생성된 인스턴스를 가리키는 변수
참조 값 생성된 인스턴스의 메모리 주소 값