자바에서의 함수는 메소드라고 하는데, 메소드의 종류에는
- Static Method : 객체가 없어도 쓸 수 있는 메소드 (클래스당 1개가 존재한다. 클래스 전체의 공용 메소드로 보면 된다.)
- Instance Method : 객체를 만들어서 쓰는 메소드 (생성된 객체마다 1개씩 존재한다. 객체 하나의 개인 메소드로 보면 된다.)
함수를 만드는 이유는 조건문, 제어문, 반복문 등을 통해서 만들어지는 기능들을 잘게 쪼개서 특정 기능만을 담아서 유지보수가 쉽게 하기 위해서이다. 또, 기능을 main함수 하나에 몰게 된다면 한 사람이 작업을 하는 동안 건들 수 없고 그로 인해 협업을 할 수 없기 때문에 기능을 분리해서 각자 특정 기능에 대해 작업을 하기 위해서 함수로 분리하는 것이다. 함수는 유지보수와 확장을 위해서 독립적이어야 하며, 최대한 다른 함수와의 결합도를 낮춰야한다.
자바는 main 함수를 담고 있으며 그 형식은 다음과 같이 구성되는데,
public class 클래스명 {
public static void main(String[] args) {
}
}
여기서 맨 앞에 있는 public은 접근지정자이며, 네 가지 종류가 존재한다.
- private : 자기 자신만 사용할 수 있다.
- protected : 같은 패키지 안에 있는 자기 자식만 사용할 수 있다.
- default : 같은 패키지 안에서만 사용할 수 있다. (명시하지 않으면 이것이 기본이다.)
- public : 누구든지 사용할 수 있다.
그리고 그 뒤에 있는 static은 함수를 Static으로 설정하는 함수이며, 그 뒤에 있는 void는 리턴값으로 함수를 호출할 때 반환되는 데이터의 형태이다. void는 반환되는 데이터가 없다는 뜻이다. (만약 반환되는 데이터가 기본 정수형이라면 int를 쓴다.) 그리고 main은 함수의 이름이며, 그 뒤에 있는 괄호는 매개변수로 함수를 호출할 때 외부에서 함수 안으로 받을 데이터이다. String[] args는 String 클래스를 배열로 받으며, 그 변수의 이름은 args로 받겠다는 의미이다.
기본적으로 프로그램을 실행하면 OS가 main 함수를 호출하며, 그 이외의 다른 모든 함수는 개발자가 직접 그 함수를 호출해야 한다. 함수를 호출하는 방식은 다음과 같이 3가지 방식이 있다. 그리고 그 방식은 참조할 대상이 무엇인가에 따라서 달라진다.
Call by name
이는 함수에 매개변수 없이 함수의 이름으로 호출하는 방식이다. 함수에게 어떤 데이터도 주지 않기 때문에 호출 방식 중에서 결합도가 제일 낮다.
public static void disp(){
이런 형식으로 만들어지며, 매개변수가 들어가는 괄호가 비어있다. 호출은 괄호를 비운채로 함수 이름 그대로 호출한다.
Call by value
이는 함수가 가지고 있는 매개변수에 값이나 값을 가지는 기본형태 변수를 넣어주는 것으로, 매개변수에 넣어준 값을 통해서 호출하는 방식이다. 이 경우 함수에 값 데이터를 복사해서 전달하는 것이기 때문에 함수로 인해서 원형 데이터가 바뀌지 않는다.
public static void disp(int a, float b){
이런 방식으로 매개변수에 기본형태 변수가 들어가며, 호출은 매개변수에 값을 직접적으로 넣거나 기본형태 변수를 넣어서 호출한다.
Call by reference
이는 함수가 가지고 있는 매개변수에 레퍼런스 변수를 넣어주는 것으로, 매개변수에 넣어준 변수를 통해서 힙 메모리에 저장된 배열이나 객체를 참조하여 호출하는 방식이다. 이 경우 참조 방식으로 전달하기 때문에 함수를 통해서 참조된 데이터의 값이나 형태를 바꿀 수 있다.
public static void disp(int[] arr){
이런 방식으로 매개변수에 레퍼런스 변수가 들어간다. 호출은 매개변수에 레퍼런스 변수(배열, 객체)를 넣어서 호출한다.
이후 과제는 배열로 만든 성적 관리 프로그램을 함수로 분리하는 것이었다. 나는 이전에 다차원 배열을 통해서 다음과 같이 과제를 만들었었다.
import java.util.Scanner;
/* 성적처리프로그램.
* 1반당 3명
* 3사람
*
* 이름, 국어, 영어, 수학, 총점, 평균
*
* 입력 : 이름, 국어, 영어, 수학
* 연산 : 총점, 평균
* 출력 : 이름, 국어, 영어, 수학, 총점, 평균
*/
public class ArrayExam4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int class_num = 0;
int stu_num = 0;
System.out.print("입력하려는 반의 수는 몇 반인가요?");
class_num = sc.nextInt();
System.out.println();
System.out.print("입력하려는 학생의 수는 몇 명인가요?");
stu_num = sc.nextInt();
System.out.println();
String[][] name = new String[class_num][stu_num];
// int kor,eng,mat,total;
int [][][]score = new int[class_num][stu_num][4];
float[][] avg = new float[class_num][stu_num];
String[] subname = {"국어", "영어", "수학"};
// 입력 (이름, 국어, 영어, 수학) + 연산 (총점, 평균)
for(int k=0;k<name.length;k++) {
for(int i=0;i<name[k].length;i++) {
System.out.print("이름을 입력해주세요 : ");
name[k][i] = sc.next();
for(int j=0;j<=subname.length-1;j++) {
System.out.print(subname[j] + " 점수를 입력해주세요 : ");
score[k][i][j] = sc.nextInt();
score[k][i][3] += score[k][i][j];
}
avg[k][i] = score[k][i][3]/(score[k][i].length-1);
System.out.println();
}
}
// 출력 (이름, 국어, 영어, 수학, 총점, 평균)
for(int k=0;k<name.length;k++) {
for(int i=0;i<name[k].length;i++)
{
System.out.println("클래스 명: "+ (k+1));
System.out.println("이름 : "+name[k][i]);
for(int j=0;j<=subname.length-1;j++) {
System.out.println(subname[j] + " 점수 : "+score[k][i][j]);
}
System.out.println("총점 : "+score[k][i][3]);
System.out.println("평균 : "+avg[k][i]);
System.out.println();
}
}
}
}
이 경우,
2024.10.12 - [코딩 공부/자바(Java)] - 배열
배열
동일한 데이터 타입의 공간을 메모리에 순차적으로 확보해야 한다면, 이 변수를 순차적으로 하나로 묶는 것이 효율적이라고 생각한다. 그래서 이를 묶는 형태를 배열이라고 한다. 배열은 대괄
cagn.tistory.com
에서 만든 학생에 여러 학생을 넣어서 배열을 한 차원 늘리고, 그 후 클래스를 넣어서 한 차원을 더 늘린 형태이다. 또, 국어, 영어, 수학 점수를 하나로 합친 형태이다.
import java.util.Scanner;
public class ArrayExam5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int class_num = 0;
int stu_num = 0;
System.out.print("입력하려는 반의 수는 몇 반인가요?");
class_num = sc.nextInt();
System.out.println();
System.out.print("입력하려는 학생의 수는 몇 명인가요?");
stu_num = sc.nextInt();
System.out.println();
String[][] name = new String[class_num][stu_num];
// int kor,eng,mat,total;
int [][][]score = new int[class_num][stu_num][4];
float[][] avg = new float[class_num][stu_num];
String[] subname = {"국어", "영어", "수학"};
inputsub(name, subname, score, sc);
controlsub(name, subname, score, avg);
outputsub(name, subname, score, avg);
}
public static void inputsub(String [][]name, String[]subname,int[][][]score,Scanner sc) {
// 입력 (이름, 국어, 영어, 수학)
for(int k=0;k<name.length;k++) {
for(int i=0;i<name[k].length;i++) {
System.out.print("이름을 입력해주세요 : ");
name[k][i] = sc.next();
for(int j=0;j<=subname.length-1;j++) {
System.out.print(subname[j] + " 점수를 입력해주세요 : ");
score[k][i][j] = sc.nextInt();
}
System.out.println();
}
}
}
public static void controlsub(String [][]name, String[]subname,int[][][]score, float[][]avg) {
// 연산 (총점, 평균)
for(int k=0;k<name.length;k++) {
for(int i=0;i<name[k].length;i++) {
for(int j=0;j<=subname.length-1;j++) {
score[k][i][3] += score[k][i][j]; // 총점
}
avg[k][i] = score[k][i][3]/(score[k][i].length-1); // 평균
}
}
}
public static void outputsub(String [][]name, String[]subname,int[][][]score,float[][]avg) {
// 출력 (이름, 국어, 영어, 수학, 총점, 평균)
for(int k=0;k<name.length;k++) {
for(int i=0;i<name[k].length;i++)
{
System.out.println("클래스 명: "+ (k+1));
System.out.println("이름 : "+name[k][i]);
for(int j=0;j<=subname.length-1;j++) {
System.out.println(subname[j] + " 점수 : "+score[k][i][j]);
}
System.out.println("총점 : "+score[k][i][3]);
System.out.println("평균 : "+avg[k][i]);
System.out.println();
}
}
}
}
나는 이 문제를 입력, 연산, 출력으로 쪼갰고, 그것들을 모두 static 함수로 따로 분리해서 적용하도록 헀다. 이는 단순히 위에 있는 main에 하나의 기능으로 뭉쳐있는 문제를 3개의 함수(기능)로 분리한 것이다.
'코딩 공부 > 자바(Java)' 카테고리의 다른 글
자바 설치 및 환경 변수 설정 (24) | 2024.10.21 |
---|---|
클래스 (12) | 2024.10.19 |
배열 - 성적 처리 프로그램 (13) | 2024.10.12 |
반복문(while문, do~while문) 및 루프 제어(break와 continue) (10) | 2024.10.11 |
다중 루프 (for문) - 구구단 문제 (4) | 2024.10.10 |