학원/Java

21-11-01 메서드, 클래스

링규 2021. 11. 1. 16:01

 

Call by Reference 방식의 메소드 호출

예제

 

배열 내 모든 정수의 합을 출력하는 메서드를 제작하시오.

 

public class Method06 {
	public static void main(String[] args) {
		
		int[] a = {56,54,87,89,25,36,57,98,59,87};
		
		sum(a);		//648
	}
	
	public static void sum(int[] arr) {
		int s = 0;
		for(int i=0; i<arr.length; i++) {
			s += arr[i];
		}
		System.out.println(s);
	}	
}

 

 

리턴 값이 존재하는 메소드의 선언

 

메서드 호출 후 메서드에서 계산되어 진 결과를 호출한 지점에서 사용하고자 할 때

return 명령으로 호출된 지점으로 전달

 

 

위에 있는 예제에서 사용한 메소드는 "출력"을 위한 메소드이기 때문에 int s의 값 즉 모든 정수의 합을 메인 메소드에서 활용할 수는 없다.(int s는 지역변수이기 때문에)

 

return을 받기 위해서는 사용해왔던 public static void의 void 대신에 return할 데이터타입을 입력해 준다

(ex : String을 return 하고 싶다면 -> public static String 함수명(매개변수) { }) 

 

import java.util.Scanner;

public class Method07 {
	public static void main(String[] args) {
		
		//리턴 값이 존재하는 메소드의 선언
		Scanner sc = new Scanner(System.in);
		System.out.print("정수를 입력하세요.");
		int num = sc.nextInt();
		int k = square(num);
		System.out.printf("%d의 제곱은 %d입니다.", num, k);
	
	}
	
	public static int square(int num) {
		int sq = num*num;
		return sq;
		
	}
}

 

출력 결과

 

sq는 지역변수이므로 메인메소드에서 사용할 수 없는 것은 변하지 않는다. 따라서 메인 메서드 내에 return된 sq의 값을 받아줄 변수가 필요하다. (위 코드에서는 int k. 같은 sq라는 이름으로도 생성이 가능하다.) 

return된 값이 일시적으로만 필요할 경우에는 

 

System.out.printf("%d의 제곱은 %d입니다.", num, square(num));

 

과 같은 형식으로 사용도 가능하다.

 

메서드의 호출과 실행, 리턴값의 구조가 반드시 리턴값을 별도의 변수에 저장되게 구성해야하는 것은 아니다. (suqare(num)만 입력하면 리턴된 값을 가지고만 있는 상태 < 이렇게 냅둬도 이상은 없다는 의미)

다만 리턴 명령의 목적이  메서드 실행 결과를 리턴받아 사용할 목적이었다면 리턴값을 별도의 변수에 저장하는 것이 설계 목적상 올바른 사용 (int k = square(num);)

 

 

예제

 

세 숫자중 가장 큰 수를 출력하라

 

public class Method07 {
	public static void main(String[] args) {
    
		int max_result = max(10, 34, 67);
		System.out.printf("가장 큰 숫자는 -> %d\n", max_result);
     
        }
	
	public static int max (int a, int b, int c) {
		int result = 0;
		
		if(a>b) result = a; 
		else result = b;
		
		if(result<c) result = c;
		return result;
		
	}
	
}

 

출력 결과

 

 

메서드의 사용에 따른 메서드 형태

 

abc( ) - 전달 인수가 없고 리턴값도 없는 형태

abc(10, 20) - 전달 인수 2개, 리턴값 없음

k = abc( ) - 전달인수가 없고 리턴값은 있음

k = abc(10, 20) - 전달 인수 2개, 리턴값이 있음

 

 

※ 개발자 필요에 의해 만들어지는 메서드는 반드시 클래스 안에 정의 되어야 하며 새애성된 메서드들 간에는 자유롭게 서로를 호출하여 사용할 수 있다. 해당 클래스에 속해있는 메서드들을 그 클래스의 "멤버"라고 부른다

단, main 메서드는 프로그램을 시작한다는 의미이기 때문에 자유롭게 호출할 수 없다.

 

 

예제

 

반지름을 입력받아 원주와 원넓이를 출력하는 메소드 작성하시오

 

import java.util.Scanner;

public class Method08 {
	public static void main(String[] args) {
		
		//반지름을 입력받아 원주와 원넓이를 출력하는 메소드 작성
		
		Scanner sc = new Scanner(System.in);
		System.out.println("반지름을 입력하세요");
		int r = sc.nextInt();
		double d = calculate2(r); // 원의 둘레를 구하는 메서드
		double n = calculate1(r);	// 원의 넓이를 구하는 메서드
		prn(n,d); //넓이와 둘레를 출력하는 메서드
		
		sc.close();
				
	}
	
	public static double calculate1 (int r) {
		double d = 2* 3.14 * r;
		return d;
	}
	
	public static double calculate2(int r) {
		double n = 3.14 * r * r;
		return n;
	}
	
	public static void prn(double d, double n) {
		System.out.printf("원주는 %.2f, 원넓이는 %.2f입니다", d, n);
	}
}

 

출력 결과

 

 

메소드 내의 코드를 아래와 같이 한 줄로 줄여 쓸 수도 있다.

 

double n = 3.14 * r * r;
return n;

//== 

return 3.14 * r * r;

 

 

예제

 

연도를 입력받아 윤년과 평년을 출력하는 메소드를 제작하시오.

 

 

import java.util.Scanner;

public class Method09 {

	public static void main(String[] args) {
		
		//입력된 연도가 윤년인지 평년인지 출력하기
		
		Scanner sc = new Scanner(System.in);
		System.out.print("년도 입력 : ");
		int year = sc.nextInt();
		boolean a = yoon(year);	//윤년이면 true, 평년이면 false를 리턴하는 메소드
		prn(year, a); //출력용 메소드
		
		sc.close();
        
	}
	
	public static boolean yoon (int year) {
		if ((year%4==0 && year%100!=0 || year%400==0)) return true;
		else return false;
	}
	
	public static void prn (int year, boolean a) {
		
		if(a==true) System.out.printf("%d년은 윤년입니다.", year);		
		if(a==false) System.out.printf("%d년은 평년입니다.", year);
		
	}
}

 

출력 결과

 

 

메소드를 만들기 전에 빨간줄에 마우스를 올려보면 아래와 같은 창이 뜨고 

 

 

create method 를 클릭하면

 

 

자동으로 메소드가 생성된다. 접근제어자를 수정하고(해야한다면) 안에 내용만 잘 채워주면 되겠다

 

 

예제

 

밑변과 높이를 입력받아 삽각형의 넓이를 계산하여 출력 (입력도 메서드를 통해 받을 것)

 

 

import java.util.Scanner;

public class Method10 {
	public static void main(String[] args) {
		
		//삼각형의 밑변과 높이를 입력받아 삼각형의 넓이를 계산하여 출력
		
		int a,b; 
		double c;
		a = myInput1();	// 밑변 입력받기
		b = myInput2();	// 높이 입력받기
		c = calculate(a,b); // 넓이 계산
		prn(c); //출력
		

	}

	public static int myInput1() {
		System.out.print("밑변을 입력하세요 : ");
		Scanner sc = new Scanner(System.in);
		int a = sc.nextInt(); 
		return a;
	}
	
	public static int myInput2() {
		System.out.print("높이을 입력하세요 : ");
		Scanner sc = new Scanner(System.in);
		int b = sc.nextInt(); 
		return b;
	}
	
	public static double calculate(int a, int b) {
		return a*b*0.5;
		
	}

	public static void prn(double c) {
		System.out.printf("삼각형의 넓이는 %.1f입니다.", c);
	}
	
}

 

출력 결과

 

 

예제와 함께 보는 메서드의 생성 순서

 

1. 함수의 용도 전달인수 및 리턴값의 유무를 파악

-> myInput은 함수 내에서 밑변 또는 높이 입력이라는 안내와 함께 정수를 입력받아 입력받은 정수를 리턴

 

2. 메서드의 호출형태(호출 구문)을 복사

-> a = myInput();

 

3. 좌항에 'a='이 있다 = 리턴값이 있다. 

-> 'a =' : public static int 

 

4. 'myIntput(1)'이라면 괄호안에 1이 있다는 것은 전달인수가 있다는것

-> public static int myInput(int k) : 변수의 자료형은 괄호 안에 전달되는 자료형과 일치 시킨다.

 

 

예제

 

점수 3개를 입력받고 총점과 평균을 출력하는 메소드를 작성하라

 

import java.util.Scanner;

public class Method11 {
	
	public static void main(String[] args) {
		int kor, eng, mat, tot;
		double ave;
		String grade;
		kor = myInput(1);	//점수입력
		eng = myInput(2); 
		mat = myInput(3); 
		tot = sum(kor, eng, mat);
		ave = avg(kor, eng, mat);
		prn(tot, ave);	//총점 평균 학점 출력
		
		
	}

	public static int myInput(int i) {
		Scanner sc = new Scanner(System.in);
		switch (i) {
		case 1 : 
			System.out.print("국어 점수를 입력하세요 : ");
			break;
			
		case 2:
			System.out.print("영어 점수를 입력하세요 : ");
			break;
		case 3 :
			System.out.print("수학 점수를 입력하세요 : ");
			break;
		}
		
		return sc.nextInt();
		
	}

	public static int sum(int kor, int eng, int mat) {
		return kor + eng + mat;
		
	}
	
	public static double avg(int kor, int eng, int mat) {
		return (kor + eng + mat)/3.0;
	}
	
	public static void prn(int t, double a) {
		
		System.out.printf("총점 : %d, 평균 %.2f", t, a);
		
	}
	
}

 

출력 결과

 

 

 

예제

 

배열의 요소와 합계, 평균을 출력하는 메소드를 작성하라.

 

public class Method12 {

	public static void main(String[] args) {
		
		int[] a = {56, 87, 96, 59, 25, 48, 13, 33, 65};
		int tot = 0;
		double ave;
		tot = sum(a); //배열의 합계
		ave = average(a);
		prn(a, tot, ave);

	}
	
	
	public static void prn(int[] a, int tot, double ave) {
		System.out.print("a[] = ");
		for(int k : a) System.out.print(k + " ");
		System.out.printf("\n배열의 총합 : %d", tot);
		System.out.printf("\n배열의 평균 : %.2f ", ave);
		
	}

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

	public static double average(int[] arr) {
		int tot = sum(arr);	// 사용자가 정의한 메서드들은 자유롭게 호출 가능
		return tot/arr.length;
	}
	
}

 

출력 결과

 

※메서드 안에서도 다른 메서드 호출이 가능하다

 

메서드 오버로딩 

 

메서드의 이름은 같고 매개변수의 타입, 갯수, 순서가 다르면 서로 다른 메서드로 인지하는 문법.

일관된 메서드 이름을 사용하여 사용자에게 직관적인 이름을 사용하게 한다.

※ 정의된 메서드들의 매개변수와 맞지 않는 호출은 에러 

 

 

public class Method13 {
	public static void main(String[] args) {
		
		//메서드 오버로딩
		
		int max_result = max(78,51,67);
		prn(max_result);
		max_result = max(56,87);
		prn(max_result);
		double max_resultD = max(123.45, 456.56);
		prn(max_resultD);
		
	}

	public static double max(double d, double e) {
		return Math.max(d, e);
	}

	public static int max(int i, int j) {
		return Math.max(i, j);
	}

	public static int max(int i, int j, int k) {
		return  (i>j)? i : (j>k)? j : k;
	}

	public static void prn(int result) {
		System.out.printf("가장 큰 값은 %d입니다\n", result);
		
	}
	
	public static void prn(double result) {
		System.out.printf("가장 큰 값은 %.2f입니다.\n", result);
	}
}

 

출력 결과

 

 

전달인수의 갯수가 일정치 않아서 오버로딩으로는 해결할 수 없을 때 : 데이터타입 ... 참조변수명

 

public class Method14 {
	public static void main(String[] args) {
		
		// 전달 인수의 갯수가 일정치 않아 오버로딩으로는 해결할 수 없는 경우
		
		int c = max(50,60, 80, 60, 54, 60);
		System.out.println("입력 값 중 가장 큰 값은 " + c + " 입니다.");
		c = max(50,60, 80, 60, 54, 60, 56, 87, 69);
		System.out.println("입력 값 중 가장 큰 값은 " + c + " 입니다.");
		
	}
	
	public static int max(int ... a) {		// 참조변수 a를 이름으로 한 배열이 생성됨.
		int max = 0;
		
		for(int i=0; i<a.length; i++) {	 	//배열의 크기는 전달되는 전달 인수의 갯수로 ...
			if (a[i] > max) max = a[i];
		}
		
		return max;
	}

}

 

출력 결과

 

전달인수가 1개 이상인 메소드를 만들 때 생성 될수도 있는 전달인수 경우의 수를 전부 메소드로 만들 수는 없기 때문에 위와 같은 방법을 사용한다.

메소드의 매개 인수 자리에 데이터타입 ... 참조변수명 을 작성하게 되면 참조변수명을 이름으로 하는 배열이 생성되고 그 배열을 사용하여 메소드를 구성할 수 있다. (예시의 경우에는 배열 내 가장 큰 값을 찾는다.)

 

 

public class Method15 {
	public static void main(String[] args) {
		
		sort("asc", 78, 25, 56, 32, 45, 78, 98);
		System.out.println();
		sort("desc", 87, 76, 12, 8, 78, 25, 56, 32, 45, 78, 98);
	}
	
	public static void sort(String op, int ... a) {
		// ...으로 처리할 데이터들을 다른 형의 참조변수보다 더 뒤에 입력해야한다.
		
		if(op.equals("asc")) {
			for(int i=0; i<a.length; i++) {
				for(int j=i+1; j<a.length; j++) {
					if(a[i]>a[j]) {
						int temp = a[i];
						a[i] = a[j];
						a[j] = temp;
					}
				}
			}
			System.out.print("asc : ");
			for(int k : a) System.out.print(k + " ");
		} else {
			for(int i=0; i<a.length; i++) {
				for(int j=i+1; j<a.length; j++) {
					if(a[i]<a[j]) {
						int temp = a[j];
						a[j] = a[i];
						a[i] = temp;
					}
					
				}
				
			}
			System.out.print("desc : ");
			for(int k : a) System.out.print(k + " ");		
		}
		
	}

}

(난리났다...)

 

출력 결과

 

이 예시에서 꼭 알아야할 것은 메소드 참조변수를 적을 때 ...이 사용되는 데이터 타입이 항상 더 오른쪽에(뒤에) 입력되야 한다는 것.

 

 

예제

 

전달된 문자열에 따라서 입력된 숫자들의 평균 또는 합계를 출력하는 메서드를 작성하라

 

public class Method16 {
	public static void main(String[] args) {
		
		// cals 생성 (전달된 문자열에 따라서 입력된 숫자들의 평균 또는 합계를 출력하는 메서드)
		
		cals("합계", 98,78,45,12,23,87,69,59);
		System.out.println();
		cals("평균", 98,78,45,12,23,87,69,57,64,25);

	}

	public static void cals (String str, int ... a) {
		int sum = 0;
		for(int i=0; i<a.length; i++) sum+=a[i];
		if (str == "합계") System.out.println("입력된 정수의 총합은 : " +  sum);
		else {	
			double avg = (double)sum/a.length;
			System.out.printf("입력된 정수의 평균은 : %.1f", avg);
		}
	}
}

 

출력 결과

 

 

예제

 

학생수와 과목수, 과목별 점수를 입력 받고 총점, 평균과 함께 성적표를 출력하시오.

 

 

 

import java.util.Scanner;

public class Method17 {

	public static void main(String[] args) {
		
		int[][] scores;
		double[] avg;
		//int s = getStudentNumber(); : 학생수를 입력받아 리턴하는 매서드
		//int k = getSubjectNumber(); : 과목수를 입력받아 리턴하는 메서드
		//scores = new int[s][k];
		
		scores = new int[getStudentNumber()][getSubjectNumber()+1];	//총점까지 저장하기위해 +1
		avg = new double[scores.length];
		input(scores);	 // s명의 학생의 k개의 과목수 입력
		cals(scores, avg);		 // 총점 평균 계산
		output(scores, avg);		// 성적표 출력

	} 
	
	public static int getStudentNumber() {
		Scanner sc = new Scanner(System.in);
		System.out.print("학생 수를 입력하세요 : ");
		return sc.nextInt();
	}
	
	public static int getSubjectNumber() {
		Scanner sc = new Scanner(System.in);
		System.out.print("과목 수를 입력하세요 : ");
		return sc.nextInt();
	
	}
	
	public static void input(int[][] arr) {
		Scanner sc = new Scanner(System.in);
		for(int i=0; i<arr.length; i++) {
			for(int j=0; j<arr[i].length-1; j++) {
				System.out.printf("%d번 학생의 %d과목 점수를 입력하세요 : ", i+1, j+1);	//0이 아닌 1부터 출력되도록 +1
				arr[i][j] = sc.nextInt();
				}
			}
		}
	
	public static void cals (int[][] arr, double[] avg) {
		int[] sum = new int[arr.length];
		for(int i=0; i<arr.length; i++) {
			for(int j=0; j<arr[i].length-1; j++) {		//총점칸은 빼기 위해 -1
				arr[i][arr[i].length-1] += arr[i][j];	//총점칸(arr[i][j])에 총점 누적
			}
			
			avg[i] = arr[i][arr[i].length-1]/(double)(arr[i].length-1);
			
		}
	}
	
	public static void output (int[][] arr, double[] a) {
		int sub = arr[0].length;	//과목수
		int std = arr.length;		//학생수 
		System.out.println();
		System.out.println("\t\t###성적표###");
		System.out.println("=============================================");
		System.out.print("번호\t");
		for(int i=0; i<sub-1; i++) System.out.printf("과목%d\t", i+1);
		System.out.print("총점\t평균\t");
		System.out.println("\n=============================================");
		for(int i=0; i<std; i++) {
			System.out.printf("%d\t", i+1);	//번호
			for(int j=0; j<sub; j++) {
				System.out.printf("%d\t", arr[i][j]);
			}
			System.out.printf("%.1f\t\n", a[i]);
		}
		System.out.println("=============================================");
	}
	
}

 

출력 결과

 

엄청나게 어려웠다.... 2차원 배열에 1차원배열까지 추가로........ 복잡해서 머리에 정리가 한번에 안된다ㅠㅠ 

설계의 필요성을 절실히 느끼는 중 ㅠ,,,,

 


 

Class

 

클래스 : 프로그램으로 처리하고자 하는 대상을 자료화하여 하나의 자료형으로 정의(속성/기능)한 사용자 정의 자료형

= 개발자가 필요에 의해 정의한 자료형 

 

 

클래스 생성과 기본 구조

 

class 클래스이름 {
	
	//멤버필드
	int 변수1;
	double 변수2;
	String 변수3;
	int [] 배열 = new int[5];
	
	//멤버 메서드 
	public void 메서드1() { }
	public static void 메서드2() {}
    
}

 

속성 (=멤버필드, 멤버변수, 필드) : 클래스에 속한 정보(변수)들

속성은 변수로 생성하며 클래스의 멤버필드라고 호칭한다.

 

 

클래스의 변수 선언

 

class First {
	//속성(멤버필드, 멤버변수, 필드) : 클래스에 속한 정보(변수)들.
	int n1;
	int n2;
    
  }

라는 클래스를 만들었을 때 새로 만들어진 클래스의 변수는 메인 메서드 안에 

클래스명 객체명; 형식으로 생성한다. (ex) First a1;

생성된 변수는 레퍼런스(참조)변수이며 배열과 마찬가지로 new 명령을 이용하여 Heap영역에 적정공간을 확보한 후 그 주소를 a1변수에 저장하여 사용한다. 

레퍼런스 변수와 new에 의해 만들어진 공간이 합쳐지면 이를 객체라고 부른다.

 

a1= new First(); 

와 같이 공간이 할당되면 이제부터 n1, n2 변수가 사용이 가능하다.

new First()로 생성된 새로운 공간을 뉴인스턴스라고 부르기로 한다.

 

public class Class01 {
	public static void main(String[] args) {
		
		First a1;
       	a1 = new First();
		First a2 = new First();
        
		System.out.println(a1.n1);
		System.out.println(a1.n2);
        
		a2.n1=30;
		a2.n2=40;
		System.out.println(a2.n1);
		System.out.println(a2.n2);
	}
}

 

객체가 두개가 만들어지면 a1에도 n1,n2가 생성되고 a2에도 n1,n2가 생성되므로 그 둘을 구분하기 위해 

a1.n1 / a1.n2 / a2.n1 / a2.n2 로 사용한다.

 

 

예제

 

student 클래스를 생성하여 성적표 출력하기

 

 

class Student {
	
	int no;
	String name;
	int kor;
	int eng;
	int mat;
	int tot;
	double ave;

	
	Student() {}
	Student(int no, String name, int kor, int eng, int mat) {
		this.no = no;
		this.name = name;
		this.kor = kor;
		this.eng = eng;
		this.mat = mat;
	
	}
	

	public static double avg (int tot) {
		return tot/3.0;
	}
	
	
	public static void information() {
		System.out.println("\t\t###성적표###");
		System.out.println("==============================================");
		System.out.println("이름 \t 국어 \t 영어 \t 수학 \t 총점 \t 평균");
	}
	
	
	public static void prn (Student a) {
		System.out.printf("%s \t %d \t %d \t %d \t %d \t %.1f\n", a.name, a.kor, a.eng, a.mat, a.tot, a.ave);	
		
	}

	
}


public class Class2 {
	public static void main(String[] args) {
		
		Student s1 = new Student(1, "홍길동", 89, 87, 93);
		Student s2 = new Student(2, "고길동", 87, 25, 65);
		s1.tot = s1.kor+s1.eng+s1.mat;
		s2.tot = s2.kor+s2.eng+s2.mat;
		s1.ave = Student.avg(s1.tot);
		s2.ave = Student.avg(s2.tot);
		Student.information();
		Student.prn(s1);
		Student.prn(s2);
		
	}
}

 

출력 결과

 

예습했었던 생성자와 메소드를 조금 이용해서 만들었다.

총점도 메소드로 묶을 수 있을 것 같았는데 잘 모르겠네 ... 

 

 


 

아마 다음시간엔 class에 배열 생성하고 학생들 이름 점수 입력받아서 출력하는 걸 하지 않을까 싶다

오늘 메서드 예제는 진짜 어려웠다 ^^.. 벌써 어려운게 나오면 어쩌쥐 큰일났다

자바 공부는 좀 뒤로 미루고 SQL 을 좀 할까 했었는데 안될 것 같다 ...........