메소드
1. 객체 지향 프로그램에서 행동에 해당하는 부분을 정의하는 것.
2. 정의하는 방법
접근지정자 기타 제어자 반환자료형 메소드명(매개 변수){
//실행문;
//return 구문;
}
3. 클래스 내부에는 멤버변수, 메소드만 정의 가능.
public class 클래스명 {
//멤버변수 정의
//메소드 정의
//클래스 차원에서는 실행문이 올 수 없다. -> 메소드 내부에만 존재가능.
}
4. 메소드에는 특별히 목적을 가진 메소드가 있다.
-> main: 프로그램의 진입점 역할
-> getter, setter : 멤버변수에 대해서 간접적인 데이터 입출력 담당.
-> 생성자 : 객체 생성에만 참여하는 전용 메소드. 멤버변수 초기화 역할 담당. 생성자는 표기하지 않아도 자동 생성 및 호출.
5. 메소드 인수 전달 방법
- Call by Value (값에 의한 전달) : 기본 자료형 간의 값 전달시 발생. 값이 복사되면서 전달
- Call by Reference (참조에 의한 전달) : 참조형 간의 값 전달시 발생. 값의 대한 참조 주소만 전달.
배열이나 String같이 참조자료형은 결국 값을 공유하게 된다는게 포인트
//Class25.java
//Class26.java
Call of Value
package com.test;
public class Class25 {
public static void main(String[] args) {
//객체생성 과정
Class25 obj = new Class25();
//인스턴스 멤버(method1()) 호출
//메소드 호출시 값 전달
//보내는 값 자료형이 int형
//Call by Value에 의한 데이터 전달 상황
//보내는 쪽은 여러개의 자료를 동시에 보낼 수 있다.
int a = 10;
System.out.println(a); //10
obj.method1(a, 20);
System.out.println(a); //10
}
//메소드에서는 매개변수 리스트를 미리 준비해야 한다.
//받는 값 자료형 역시 int형
//받는 쪽은 보내는 쪽 자료의 자료형, 갯수, 순서에 맞춰서 준비.
public void method1(int a, int b) {
//메소드도 호출한 쪽에 데이터를 되돌려 줄 수 있다.
//return 구문 사용.
//되돌려줄 수 있는 데이터는 한 개만 가능.
//return 구문 사용시에는 void가 아닌 특정 자료형을 표시.
a += b;
System.out.println(a); //30
}
}
Call of Reference
package com.test;
public class Class26 {
public static void main(String[] args) {
//객체생성 과정
Class26 obj = new Class26();
//인스턴스 멤버(method1()) 호출
//메소드 호출시 값 전달
//보내는 값 자료형이 int형 배열
//Call by Reference에 의한 데이터 전달 상황
//보내는 쪽은 여러개의 자료를 동시에 보낼 수 있다.
int[] a = {10};
System.out.println(a[0]); // 10
obj.method1(a, 20);
System.out.println(a[0]); // 30
}
//메소드에서는 매개변수 리스트를 미리 준비해야 한다.
//받는 값 자료형 역시 int형 배열
//받는 쪽은 보내는 쪽 자료의 자료형, 갯수, 순서에 맞춰서 준비.
public void method1(int[] a, int b) {
//메소드도 호출한 쪽에 데이터를 되돌려 줄 수 있다.
//return 구문 사용.
//되돌려줄 수 있는 데이터는 한 개만 가능.
//return 구문 사용시에는 void가 아닌 특정 자료형을 표시.
a[0] += b;
System.out.println(a[0]); // 30
}
}
문제)return구문 없이 결과값 돌려받는 메소드 구현. 최대값, 최소값 얻기
실행 예)
입력할 숫자의 갯수 지정(2~10)?3
숫자1?XX
숫자2?YY
숫자3?ZZ
입력 받은 숫자 : XX, YY, ZZ
가장 큰 숫자 : ZZ
//가장 큰 숫자를 리턴하는 메소드 구현
public void max(int[] arr) {
//가장 큰 값 얻는 과정 추가
}
//Calc.java
//Class27.java
package com.test;
public class Calc {
public void maxArray(int[] arr) {
int temp = 0;
for(int a=0; a<arr.length-1; a++){
if (arr[a] >= arr[a+1]) {
temp = arr[a];
arr[a] = arr[a+1];
arr[a+1] = temp;
}
}
}
}
package com.test;
import java.util.*;
public class Class27 {
public static void main(String[] args) {
//입력
Scanner sc = new Scanner(System.in);
System.out.print("입력할 숫자의 갯수 지정(2~10)?");
int size = sc.nextInt();
//배열 생성
int[] arr = new int[size];
//생성된 배열에 각 숫자를 넣기
for (int a=0; a<arr.length; a++) {
System.out.printf("숫자%d?", a+1);
arr[a] = sc.nextInt();
}
System.out.print("입력 받은 숫자: ");
for (int a=0; a<arr.length; a++) {
System.out.printf("%d ", arr[a]);
}
//처리
Calc obj = new Calc();
//Call by Reference
//return 구문이 없는 메소드이므로, 되돌려받는 데이터도 없다.
obj.maxArray(arr);
//출력
System.out.println();
//maxArray 내부에서의 액션에 의해 가장 큰 숫자는 배열의 가장 끝 위치에 존재한다.
System.out.printf("가장 큰 숫자: %d", arr[arr.length - 1]);
}
}
문제) 사용자가 직접 sort() 메소드 구현. Test.sort(배열); 형태로 구성할 것.
//Test.java
//Class28.java
package com.test;
public class Test {
public static void sort(int[] arr) {
for (int n=1; n<(arr.length) ; n++) {
for (int i=0; i < (arr.length-n); i++) {
if (arr[i]>arr[(i+1)]) {
int temp = arr[i];
arr[i] = arr[(i+1)];
arr[(i+1)] = temp;
}
}
}
}
}
public class Class28 {
public static void main(String[] args) {
int[] arr={3, 2, 1, 5, 7, 6, 9, 4, 8, 0};
System.out.print("정렬 전 : ");
for(int a=0; a<arr.length; a++){
System.out.printf("%d ", arr[a]);
}
System.out.println();
Test.sort(arr); //Call by Reference
System.out.print("정렬 후 : ");
for(int a=0; a<arr.length; a++){
System.out.printf("%d ", arr[a]);
}
System.out.println();
}
}
되부름(Recursion)
1. 메소드는 다른 메소드를 호출하여 이용할 수 있을 뿐 아니라 자기 자신의 메소드를 다시 호출하여 사용할 수 있다.
-> 주의. 무한 실행이 될 수도 있음.
public void method1() {
if(조건) {
return; //반환자료형이 void에서 return을 사용하면 메소드 종료를 의미.
}
method1(); //되부름
}
//Class29.java
package com.test;
public class Class29 {
public static void main(String[] args) {
Class29 obj = new Class29();
//obj.method1(); //1. 무한실행.
//obj.method2(0);
//obj.method3(0);
System.out.println(obj.method4(10)); // 10+9+8+...+1
}
public void method1() { //2, 6, 10, ...
int a=0; //3, 7, ...
System.out.println(++a); //4, 8, ...
method1(); //되부름 //5, 9, ...
}
public void method2(int a) {
System.out.println(++a);
method2(a);
}
public void method3(int a) {
if (a >= 10) {
return; //메소드 실행 종료
}
System.out.println(++a);
method3(a);
}
public int method4(int a) {
return (a>1) ? a+method4(a-1) : a;
}
//10 + method(9)
//10 + (9 + method(8))
// ...
}
문제) 팩토리얼(n!) 계산해서 출력. recursion 사용할 것. 반복문 이용 불가.
1 * 2 * 3 * 4 * 5 * 6 * ... * n -> xxxx
10! -> 3628800
실행 예)
팩토리얼 값(2~10)?
1! -> 1
2! -> 2
3! -> 6
4! -> 24
...
10! -> 3628800
//Class30.java
package com.test;
import java.util.*;
public class Class30 {
public static void main(String[] args) {
System.out.print("팩토리얼 값(2~10)?");
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
Class30 obj = new Class30();
obj.recursion1(0, a);
}
//1~n 까지 출력하는 메소드
public void recursion1(int n, int end) {
if (n>= end) {
return;
}
System.out.printf("%d! -> %d %n", ++n, recursion2(n));
recursion1(n, end);
}
//n! 계산하는 메소드
public int recursion2(int n) {
return (n>1) ? n*recursion2(n-1) : n;
}
}
문제) 밑수, 지수를 받아서 제곱승 출력, recursion 이용.
실행 예)
입력(밑수 지수)?2 10
2^10 -> 1024
//Class31.java
package com.test;
import java.util.Scanner;
public class Class31 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("입력 (밑수 지수)?");
int n = sc.nextInt();
int m = sc.nextInt();
Class31 obj = new Class31();
System.out.printf("%d^%d -> %d %n"
, n, m, obj.recursion(n, m));
}
public int recursion(int n, int m) {
return (m>1) ? n*recursion(n, m-1) : n;
}
}
생성자
1. 객체 생성을 담당하는 전용 메소드. 자동 생성되기 때문에 표기하지 않고 생략하는 경우가 많음.
2. 멤버 변수 초기화 역할 담당.
3. 생성자 정의
public class 클래스명 {
//생성자
//반환자료형이 없다.
//메소드명은 클래스명으로만 가능.
//기본 생성자는 컴파일러에 의해 자동 생성되므로 주로 생략함.
public 클래스명() {
}
public static void main(String[] args) {
//생성자 호출 부분
클래스명 객체변수 = new 클래스명();
}
}
4. 멤버 변수 초기화 역할을 하는 경우는 반드시 생성자를 표기해야 한다.
public class 클래스명 {
//멤버 변수
자료형 변수명;
//생성자
//반환자료형이 없다.
//메소드명은 클래스명으로만 가능.
//기본 생성자는 컴파일러에 의해 자동 생성되므로 주로 생략함.
//매개변수가 존재하는 생성자 표기시 반드시 기본 생성자를 같이 표기해야 한다.
//동일한 명칭을 가진 메소드가 두개 이상인 경우를 메소드 오버로딩 상태라고 함.
//생성자가 두개인 경우는 생성자 오버로딩(constructor overloading)
public 클래스명() {
}
public 클래스명(매개변수 리스트) {
변수명 = 값;
}
public static void main(String[] args) {
//생성자 호출 부분
클래스명 객체변수 = new 클래스명();
}
}
//Class32.java
package com.test;
public class Class32 {
//기본 생성자는 생략가능.
public Class32() {
System.out.println("Class32의 기본생성자 호출");
}
public static void main(String[] args) {
//기본 생성자 호출 과정
Class32 obj = new Class32();
// obj.Class32(); // 생성자는 일반 메소드가 아니므로 이 표현 방법은 틀림
}
}
//Class33.java
package com.test;
public class Class33 {
private int a, b;
//기본생성자 생략 가능
//생성자 오버로딩 -> 기본 생성자 생략 불가.
public Class33() {
}
public Class33(int a) {
this.a = a;
}
public int getA() {
return a;
}
public static void main(String[] args) {
//(인스턴스) 멤버 변수 a에 대한 접근 시도 -> 에러
//System.out.println(a);
//객체 생성 과정 필수.
Class33 obj1 = new Class33();
System.out.println(obj1.a);
//오버로딩된 생성자 호출 과정
Class33 obj2 = new Class33(10);
System.out.println(obj2.a);
//멤버변수 a에 대한 접근은 getter를 이용할 것.
Class33 obj3 = new Class33();
System.out.println(obj3.getA());
}
}
this 생성자
1. this 키워드는 생성된 객체를 지정하는 자기 자신을 의미하는 용어.
2. 객체가 생성될 예정인 경우 미리 변수 선언을 할 수 없으므로, this 키워드로 표현. 객체가 생성되면 그때 비로소 참조주소가 저장된다.
예를 들어 홍길동이라는 객체가 있다면
홍길동 -> 3인칭
나, 너 -> 1, 2인칭
홍길동 입장에서는 '나'라는 표현이 바로 홍길동 자신을 의미.'나'에 해당하는 표현이 바로 this 키워드의 역할.
public class 클래스명 {
private 자료형 변수;
public 클래스명() {
//this 생성자
this(값); // this 키워드 생략불가
}
public 클래스명(자료형 변수) {
this.멤버변수 = 변수; // this 키워드 생략불가
}
public void method1() {
this.method2(); //this 키워드 생략가능
}
public void method2() {
}
}
//Class34
package com.test;
public class Class34 {
private int a; //멤버변수 // 자동초기화 지원
private int b;
public Class34(){ //기본생성자 // 2
this(10); //this 생성자 // 3
}
public Class34(int a) { //생성자 오버로딩 // 4
this(a, 10); //5
}
//생성자 오버로딩
public Class34(int a, int b) { //6
this.a = a; //7
this.b = b; //8
}
public int getA() {
return a;
}
public int getB() {
return b;
}
public static void main(String[] args) {
//기본생성자 호출과정
Class34 obj = new Class34(); //1
System.out.println(obj.getA()); //10
System.out.println(obj.getB()); //10
//오버로딩된 생성자 호출과정
Class34 obj2 = new Class34(20);
System.out.println(obj2.getA()); //20
System.out.println(obj2.getB()); //10
//오버로딩된 생성자 호출과정
Class34 obj3 = new Class34(20, 30);
System.out.println(obj3.getA()); //20
System.out.println(obj3.getB()); //30
}
}
문제) n부터 m까지의 합을 계산해서 출력. 생성자 이용.
실행 예)
숫자1(n)?1
숫자2(m)?100
1부터 100까지의 합 : 5050
//Calc2.java
//Class35.java
package com.test;
public class Calc2 {
private int n, m;
public Calc2() {
this(1, 10);
}
//외부에서 전달된 값을 멤버변수에 저장하는 방법
public Calc2(int n, int m) {
this.n = n;
this.m = m;
}
public int getN() {
return n;
}
public int getM() {
return m;
}
public int result() {
//n부터 m까지의 합 리턴하는 전용 메소드
int sum = 0;
for (int a=n; a<=m; a++) {
sum += a;
}
return sum;
}
}
package com.test;
import java.util.Scanner;
public class Class35 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("숫자1(n)?");
int n = sc.nextInt();
System.out.print("숫자1(m)?");
int m = sc.nextInt();
Calc2 obj1 = new Calc2();
System.out.printf("%d부터 %d의 합 : %d %n"
, obj1.getN()
, obj1.getM()
, obj1.result());
Calc2 obj2 = new Calc2(n, m);
System.out.printf("%d부터 %d의 합 : %d %n"
, obj2.getN()
, obj2.getM()
, obj2.result());
}
}
멤버변수 초기화 과정
1. 자동 초기화 > 초기화 수식 > 초기화 블럭 > 생성자
2. 자동 초기화, 초기화 수식, 초기화 블럭을 이용하면 외부에서 전달 받은 데이터를 가지고 초기화 시키지는 못함.
3. 동일한 멤버변수에 대해서 자동 초기화, 초기화 수식, 초기화 블럭, 생성자에 의한 초기화 과정을 모두 거치게 되면
최종적으로 생성자에 의한 초기값만 남게됨.
4. 초기화 과정은 객체가 생성되는 과정에서 자동 실행된다.
public class 클래스명 {
private int a; //자동 초기화
private int b = 10; //초기화 수식
private int c = 10; //초기화 수식
{ //초기화 블럭 (인스턴스 멤버용) -> 제어문 등 사용이 가능.
this.b = 20;
this.c = 20;
}
public 클래스명() { //생성자에 의한 초기화
this.c = 30;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
public int getC() {
return c;
}
}
//Class36.java
package com.test;
public class Class36 {
//자동초기화
private int a; // 0
//초기화 수식
private int[] b = new int [10]; // -> 0
//초기값으로 1~10까지 10개를 저장하고 싶다면?
//반복문 처리.
//private int[] c = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
private int[] c;
{// 초기화 블럭
c = new int[10];
for (int i=0; i<c.length; i++) {
c[i] = i+1;
}
}
public int[] getB() {
return b;
}
public int[] getC() {
return c;
}
public static void main(String[] args) {
//b, c 배열에 대한 초기화 과정은 객체 생성 과정에서 자동 실행
Class36 obj = new Class36();
//b배열의 값 출력
for (int a=0; a<(obj.getB()).length; a++) {
System.out.printf("%d ", obj.getB()[a]);
}
System.out.println();
//c배열의 값 출력
for (int a=0; a<(obj.getC()).length; a++) {
System.out.printf("%d ", obj.getC()[a]);
}
System.out.println();
}
}
setter와 생성자에 의한 멤버변수 초기화 과정 비교
//Class37.java
package com.test;
public class Class37 {
private int a;
public Class37(){
}
public Class37(int a) {
this.a = a;
}
public int getA(){
return a;
}
public void setA(int a){
this.a = a;
}
public static void main(String[] args){
Class37 obj1 = new Class37();
System.out.println(obj1.getA());
Class37 obj2 = new Class37(10);
System.out.println(obj2.getA());
//생성자에 초기화는 객체 생성시 한번만 가능
Class37 obj3 = new Class37(10);
//멤버변수에 대한 값을 재지정하는 경우는 setter에 의해 여러번 가능
obj3.setA(20);
System.out.println(obj3.getA());
//객체 생성을 새로 하게 되면 새로운 객체가 되므로 이전의 멤버변수가 아닌 상태이다.
Class37 obj4 = new Class37(20);
System.out.println(obj4.getA());
}
}
문제) 여러명의 국어, 영어, 수학 점수를 입력 받아서
총점, 평균, 판정, 등수, 과목별 판정, 과목별 평균 결과 출력. 배열, 클래스 이용.
판정 기준은
합격 -> 과목별로 40점 이상이면서, 평균이 60점 이상
과락 -> 과목중에 40점 미만이 있고, 평균은 60점 이상
불합격 -> 평균이 60점 미만
평균이 60점 이상 -> 합격
평균이 60점 미만 -> 불합격
합격 또는 과락 구분은 -> 국어, 영어, 수학 점수가 모두 40점 이상인 확인.
과목별 판정 기준은
90점 이상은 A
80점 이상은 B
70점 이상은 C
60점 이상은 D
60점 미만은 F
실행 예)
인원수 입력(1~10)?2
성적 입력(이름 국어 영어 수학)?hong 100 100 100
성적 입력(이름 국어 영어 수학)?kim 80 90 80
-----------------------------------------
이름 국어 영어 수학 총점 평균 판정 등수
-----------------------------------------
hong 100(A) 100(A) 100(A) 300 100.0 합격 1
kim 80(B) 90(A) 80(B) .. .. 합격 2
과목평균 xxx.x xxx.x xxx.x
-----------------------------------------
//Class38..
//기존 코드와 완전 동일하며, main 메소드 내 코등에 아래의 내용이 추가됨
/* 추가코딩 시작 */
// 각 과목의 총합계 변수
double koravg=0, engavg=0, matavg=0;
for (int a=0; a<stu.length; a++){
koravg += stu[a].getKor();
engavg += stu[a].getEng();
matavg += stu[a].getMat();
}
koravg /= size;
engavg /= size;
matavg /= size;
/* 추가코딩 끝 */
------------------------------------------------------------------------
/* 추가코딩 시작 */
System.out.printf("과목평균 %3.1f %3.1f %3.1f %n", koravg, engavg, matavg);
/* 추가코딩 끝 */