3.8 기본형 매개변수와 참조형 매개변수

  • 기본형 : 변수의 값을 읽기만 가능(값의 복사본)
  • 참조형 : 변수의 값을 일고 변경 가능(값의 주소를 참조)

기본형 매개변수

package ch06;
class Data { int x; }

class PrimitiveParamEx {
	public static void main(String[] args) {
		Data d = new Data();
		d.x = 10;
		System.out.println("main() : x = " + d.x);

		change(d.x);
		System.out.println("After change(d.x)");
		System.out.println("main() : x = " + d.x);
	}

	static void change(int x) {  // 기본형 매개변수
		x = 1000;
		System.out.println("change() : x = " + x);
	}
}

참조형 매개변수

package ch06;
// class Data { int x; }

class ReferenceParamEx {
	public static void main(String[] args) {

		Data d = new Data();
		d.x = 10;
		System.out.println("main() : x = " + d.x);

		change(d);
		System.out.println("After change(d)");
		System.out.println("main() : x = " + d.x);

	}

	static void change(Data d) { // 참조형 매개변수
		d.x = 1000;
		System.out.println("change() : x = " + d.x);
	}
}

배열의 참조형 매개변수

package ch06;
class ReferenceParamEx2 {
	public static void main(String[] args) 
  {
		int[] x = {10};  // 크기가 1인 배열. x[0] = 10;
		System.out.println("main() : x = " + x[0]);

		change(x);
		System.out.println("After change(x)");
		System.out.println("main() : x = " + x[0]);
	}

	static void change(int[] x) { // 참조형 매개변수
		x[0] = 1000;
		System.out.println("change() : x = " + x[0]);
	}
}

메서드로 배열을 다루는 여러 방법

package ch06;
class ReferenceParamEx3 {
	public static void main(String[] args) 
	{
		int[] arr = new int[] {3,2,1,6,5,4};

		printArr(arr);  // 배열의 모든 요소를 출력
		sortArr(arr);   // 배열을 정렬
		printArr(arr);  // 정렬후 결과를 출력
		System.out.println("sum="+sumArr(arr)); // 배열의 총합을 출력
	}

	static void printArr(int[] arr) {  // 배열의 모든 요소를 출력
		System.out.print("[");

		for(int i : arr)  // 향상된 for문
			System.out.print(i+",");
		System.out.println("]");
	}

	static int sumArr(int[] arr) {  // 배열의 모든 요소의 합을 반환
		int sum = 0;

		for(int i=0;i<arr.length;i++)
			sum += arr[i];
		return sum;
	}

	static void sortArr(int[] arr) {  // 배열을 오름차순으로 정렬
		for(int i=0;i<arr.length-1;i++)
			for(int j=0;j<arr.length-1-i;j++)
				if(arr[j] > arr[j+1]) {
					int tmp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = tmp;
				}
	} // sortArr(int[] arr)
}

반환값 없는 메서드 구현

package ch06;
class ReturnTest {
	public static void main(String[] args) {
		ReturnTest r = new ReturnTest();

		int result = r.add(3,5);
		System.out.println(result);

		int[] result2 = {0}; // 배열을 생성하고 result2[0]의 값을 0으로 초기화
		r.add(3,5,result2);  // 배열을 add메서드의 매개변수로 전달
		System.out.println(result2[0]);
	}

	int add(int a, int b) {
		return a + b;
	}

	void add(int a, int b, int[] result) {
		result[0] = a + b;  // 매개변수로 넘겨받은 배열에 연산결과를 저장
	}
}

3.9 참조형 반환타입

  • 참조형 타입의 값은 객체의 주소 정수 값이므로 특별한 것이 없음
package ch06;
class Data3 { int x; }

class ReferenceReturnEx {
	public static void main(String[] args) 
	{
		Data3 d = new Data3();
		d.x = 10;

		Data3 d2 = copy(d); 
		System.out.println("d2" + d2.toString());
		System.out.println("d.x ="+d.x);
		System.out.println("d2.x="+d2.x);
	}

	static Data3 copy(Data3 d) {
		Data3 tmp = new Data3();
		tmp.x = d.x;
		
		System.out.println("tmp" + tmp.toString());
		
		return tmp;
	}
}


 

3.10 재귀호출(recursive call)

  • 메서드 내부에서 메서드 자신을 다시 호출 하는 것
  • 메서드 호출이라는 것은 특정 위치의 저장되어 있는 명령을 수행 하는 것
  • 대부분의 재귀호출은 반복문으로 가능

팩토리얼 구하기

  • f(n) = n * f(n-1), 단 f(1) = 1
  • 5! = 54321
package ch06;
class FactorialTest {
	public static void main(String args[]) {
		int result = factorial(4);  // int result = FactorialTest.factorial(4);

		System.out.println(result);
	}

	static int factorial(int n) {
		int result=0;

		if ( n == 1) {
			result = 1;		
		} else {
			result = n * factorial(n-1);		// 다시 메서드 자신을 호출한다.
		}

		return result;
	}
}

반복문 사용

package ch06;
class FactorialTestA {
	public static void main(String args[]) {
		int result = factorial(4);  // int result = FactorialTest.factorial(4);

		System.out.println(result);
	}

	static int factorial(int n) {
		int result=1;

		while(n != 0) {
			result *= n--;
		}
		return result;
	}
}

팩토리얼 최종

package ch06;
class FactorialTest2 {
	static long factorial(int n) {
		if(n<=0 || n>20) return -1;  // 매개변수의 유효성 검사.
		if(n<=1) 
			 return 1;
	    return n * factorial(n-1); 
	}

	public static void main(String args[]) {
		int  n = 21;
		long result = 0;

		for(int i = 1; i <= n; i++) {
			result = factorial(i);

			if(result==-1) {
				System.out.printf("유효하지 않은 값입니다.(0<n<=20):%d%n", n);
				break;
			}

			System.out.printf("%2d!=%20d%n", i, result);
		}
	} // main의 끝
}

x^1 ~ x^n 합 재귀함수로 구해보기

  • f(x, n) = x * f(x, n-1), 단 f(x,1) = x
package ch06;
class PowerTest { 
	public static void main(String[] args) { 
		// 2^1 + 2^2 + 2^3 + 2^4 + 2^5
		int x = 2; 
		int n = 5; 
		long result = 0; 

		for(int i=1; i<=n; i++) { 
			result += power(x, i); 
		} 

		System.out.println(result); 
	} 

	static long power(int x, int n) { 
		if(n==1) return x; 

		return x * power(x, n-1);
	} 
}

 

3.11 클래스 메서드(static 메서드)와 인스턴트 메서드

  • 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static 사용
  • 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용
  • 클래스 메서드(static 메서드)는 인스턴스 변수 사용 불가
  • 메서드 내에서 인스턴스 변수를 사용하지 않는 다면 static 사용 고려
package ch06;
class MyMath2 {
	long a, b;
	
	// 인스턴스변수 a, b만을 이용해서 작업하므로 매개변수가 필요없다.
	long add() 	    { return a + b; }  // a, b는 인스턴스변수
	long subtract() { return a - b; }
	long multiply() { return a * b; }
	double divide() { return a / b; }

	// 인스턴스변수와 관계없이 매개변수만으로 작업이 가능하다.
	static long   add(long a, long b) 	   	 { return a + b; } // a, b는 지역변수
	static long   subtract(long a, long b)   { return a - b; }
	static long   multiply(long a, long b)	 { return a * b; }
	static double divide(double a, double b) { return a / b; }
}

class MyMathTest2 {
	public static void main(String args[]) {
		// 클래스메서드 호출. 인스턴스 생성없이 호출가능
		System.out.println(MyMath2.add(200L, 100L));
		System.out.println(MyMath2.subtract(200L, 100L));
		System.out.println(MyMath2.multiply(200L, 100L));
		System.out.println(MyMath2.divide(200.0, 100.0));

		MyMath2 mm = new MyMath2(); // 인스턴스를 생성
		mm.a = 200L;
		mm.b = 100L;
		// 인스턴스메서드는 객체생성 후에만 호출이 가능함.
		System.out.println(mm.add());
		System.out.println(mm.subtract());
		System.out.println(mm.multiply());
		System.out.println(mm.divide());
	}
}

 

3.12 클래스 멤버와 인스턴스 멤버간의 참조와 호출

  • 클래스멤버가 인스턴스 멤버를 참조 또는 호출 하는 경우는 인스턴스 생성 필요
  • 클래스멤버 존재 시점에 인스턴스 맴버 존재 하지 않기 때문
  • static 메서드는 인스턴스 변수 사용 불가
package ch06;
class MemberCall {
	int iv = 10;
	static int cv = 20;

	int iv2 = cv;
//	static int cv2 = iv;		// 에러. 클래스변수는 인스턴스 변수를 사용할 수 없음.
	static int cv2 = new MemberCall().iv;	 // 이처럼 객체를 생성해야 사용가능.

	static void staticMethod1() {
		System.out.println(cv);
//		System.out.println(iv); // 에러. 클래스메서드에서 인스턴스변수를 사용불가.
		MemberCall c = new MemberCall();	
		System.out.println(c.iv);   // 객체를 생성한 후에야 인스턴스변수의 참조가능.
}

	void instanceMethod1() {
		System.out.println(cv);		
		System.out.println(iv); // 인스턴스메서드에서는 인스턴스변수를 바로 사용가능.
}

	static void staticMethod2() {
		staticMethod1();
//		instanceMethod1(); // 에러. 클래스메서드에서는 인스턴스메서드를 호출할 수 없음.
		MemberCall c = new MemberCall();
		c.instanceMethod1(); // 인스턴스를 생성한 후에야 호출할 수 있음.
 	}
	
	void instanceMethod2() {	// 인스턴스메서드에서는 인스턴스메서드와 클래스메서드
		staticMethod1();		//  모두 인스턴스 생성없이 바로 호출이 가능하다.
		instanceMethod1();
	}
}

이전글

[JAVA] - chap 06 객체지향 프로그래밍 I(object-oriented programming I)_1

[JAVA] - chap 06 객체지향 프로그래밍 I(object-oriented programming I)_2


+ Recent posts