Programming/Java

[Java9 프로그래밍] 07. 함수(메소드)

빠모스 2020. 3. 13. 19:49
반응형

함수와 메소드

  • Java에서 함수와 메소드는 동일하게 사용
  • 메소드가 좀더 기술적으로 맞는 용어
  • 클래스 내부에 있는 함수를 특별히 메소드라고 함 (자바는 모든 것이 클래스로 구성)
  • main 메소드가 길어지면 클래스로 분리 또는 여러 함수로 분리 가능

 

메소드 구조

 

  • 반환값의 타입 (없으면 void)
  • 메소드 이름
  • 파라미터 타입과 이름
  • 메소드 구현부 - 구현할 내용 작성
  • 반환할 결과가 있으면 return

public class 클래스 {

접근제한자 반환타입 메소드명 (파라미터타입 파라미터명, ,,,) {

…수식…

return 반환변수 혹은 값 혹은 수식

}

}

 

=> 접근제한자 : 메소드는 클래스 내부에서 정의가 되는데, 메소드가 모든 사람이 사용할 수 있는지, 특별한 사람만 사용할 수 있는지 메소드 사용 권한과 관련되어 제한할 수 있다.

 

 

정적 메소드 선언하고 호출하기

 

<예시 1>

입력인자로 받은 x와 y의 평균을 구해주는 함수 average를 선언하고, 호출하는 코드

// 정적 메소드 선언
public static double average(double x, double y) {
	double sum = x + y;
	return sum / 2;
}

// main 메소드에서 호출
public static void main(String[] args) {
	double a = …;
	double b = …;
	double result = average(a,b);
	//...
}

=> main 함수가 static이기 때문에 main에서 호출하는 average함수도 static이어야 한다.

a, b가 파라미터로서 average를 호출하게 되고, 각각 double x, double y에 대입되게 된다.

 

 

배열 파라미터와 반환 값

 

  • 배열도 파라미터로 전달 가능
  • 배열은 참조를 통해 전달되어 배열의 내용을 바꿀 수 있음
  • 배열도 반환 가능
// 배열 안에 두 요소를 맞바꾸는 메소드
public static int[] firstLast(int[] values) {
	if (values.Length == 0) return new int[0];
	else return new int[] { values[0],
	values[values.Length-1] };
}

자바의 타입을 굳이 두가지로 나눈다면 기본타입과 객체타입 두가지로 나눌 수 있다. 

8가지의 기본 타입을 제외한 모든것은 객체타입이다. 고로, 배열도 객체타입으로 내부적으로 인식이 된다.

그래서 배열이 파라미터로 넘어갈때와 기본타입이 파라미터로 넘어갈 때 다르다.

내부 메모리에서 데이터를 관리하는 방식이 다르기 때문이다. 

 

 

가변 인자

 

  • 파라미터의 개수를 제한하지 않고 여러 개의 파라미터를 받을 수 있음
  • 대표적으로 printf 함수가 있음
  • 가변 인자는 반드시 메소드 마지막 파라미터이어야 함
// 파라미터가 double 배열로 전달됨
public static double average(double… values) {
	double sum = 0;
	for (double v : values) sum += v;
	return values.Length==0 ? 0 : sum / values.Length;
}

=> 가변인자는 Java8에서 등장했는데, 타입 뒤에 …을 붙여주고 그 뒤에 변수명을 붙여준다. 

즉, double 타입의 파라미터를 n개 받을 수 있다. values는 double인자인 배열로 받아진다.

 

 

Call by Value - 값에 의한 호출

 

  • 기본 자료형에 적용
  • 변수에 값 자체를 저장
  • 변수를 복사하면 변수의 값 자체를 복사

 

자바의 자료형 타입 두가지

  • 기본 Primitive
  • 객체 Referential

값에 의한 호출은 기본 자료형에 적용된다.

 

 

Variable Value Address 

 

=> 기본타입은 변수를 선언하면 메모리 공간 네모에 값 자체가 직접 저장된다. 그래서 변수를 복사하면 변수의 값 자체를 복사한다. 그래서 파라미터로 전달하더라도 값 자체가 복사되어 함수 내부로 전달된다.

 

a라는 변수를 선언하고 파라미터로 넘겨주면 a 변수 자체가 넘어가는게 아니라 a의 값인 10이 복사되어 넘어간다. 즉, 메소드 내부에서 이 값이 변형이 되더라도 이 원본 a의 값은 전혀 변하지 않는다. 

 

 

Call by Reference - 참조값에 의한 호출

 

  • 배열이나 객체를 참조
  • 변수에는 값이 아니라 객체의 주소값(참조)이 저장
  • 변수를 복사하면 주소가 복사되어 하나의 객체를 참조하게 됨.

<예시 1>

String s1 = “first”;

String은 객체 타입이기 때문에 s1이라는 메모리 공간에 변수가 만들어지지만, 이 s1 공간 자체에 first가 저장되는게 아니다.

“first”라는 실제 컨텐츠는 별도 메모리 공간에 생긴다. 이 별도의 메모리 공간을 heap이라 한다.

이 heap에서 “first”가 저장된 주소값이 s1에 저장된다.

기본타입은 Stack 자체에 변수의 값이 저장되고 객체타입은 Heap을 이용해서 변수 실제 값이 Heap에 저장되게 된다. 

즉, s1을 파라미터로 메소드를 호출하게 되면 그 값인 ‘first’가 아니라 ‘first’가 저장된 주소값을 넘겨주게 된다.

 

 

=> 만약 s2에서 값을 수정하게 된다면 s1에도 영향을 미친다. 

 

 

ThinkPoint

메소드의 사용이 어플리케이션의 품질 향상에 어떻게 기여할까?

함수는 재사용성을 높여준다. 재사용성은 기존의 개발된 코드를 재사용하기에 생산성이 좋아지고 , 여러 군데에서 재사용하면서 코드가 검증이 수행되어 전체적으로 품질을 높여주는 효과가 있다.

 

실습 코드

package java9Politec;

import java.util.List;
import java.util.Arrays;

public class Lesson08_Method {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a = 5;
		int b = 3;
		
		int result = add(a, b);
		System.out.println(result);
		
		// Call by Value 함수 호출하기. 
		int byValue = 5;
		callByValue(byValue);
		System.out.println(byValue);
			// call by value 함수를 통해 5 + 5 = 10이 되야하지만 원본인 byValue는 5로, 메소드 호출 후에도 바뀌지 않음.
			// 왜? 값으로 호출할때는 원본이 넘어가는게 아니라 값의 복사본이 넘어가기 때문. 
		
		// Call by Reference 함수 호출하기. 
		List<String> byRef = new ArrayList<>();
		byRef.add("red");
		byRef.add("blue");
		System.out.println(byRef);
		callByReference(byRef);
		System.out.println(byRef);
			// 메소드 넘기기 전엔 레드, 블루였는데 넘기고 나니 화이트가 추가됨을 확인. 
			// 변수를 복사해서 넘기는게 아니라, 실제 객체의 주소값을 넘기기 때문에 메소드 내부에서는 주소값 내부에 있는 실제 리스트의 컨텐츠를 변경한다. 
			// 그렇기 때문에 실제 원본도 변경되게 된다. 
	}
	
	// 메소드로 분리 
	public static int add(int first, int second) {
		return first + second;
	}
	
	// Call by Value
	public static void callByValue(int param) {
		param = param + 5;
	}
	
	// Call by Reference
	public static void callByReference(List param) {
		param.add("white");
	}
	
}
반응형