21-11-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 을 좀 할까 했었는데 안될 것 같다 ...........