프로그래밍/TIL(국비과정)

TIL #4 - 메소드, 배열 등

양아무개 2020. 3. 30. 20:33

 

# 오버로딩

오버로딩(overloading)은 오버라이딩과 다르다. 

오버라이딩은 뒤에 배우기로 하고 

오버로딩은 기능은 같으나 파라미터가 달라지는 경우를 말한다. 

파라미터가 다르다는 것은 어떤 의미일까?

더보기

1. 파라미터의 갯수

2. 파라미터의 데이터 타입 

위의 두개가 다르면 파라미터가 다르다고 본다. 

파라미터의 이름은 파라미터가 달라지는데에 영향이 없다고 한다. 

예를 들어, 

더보기

public int add(int number1, int number2) 

public int add(int positiveNumber1, int positiveNumber2)

위와 같이 파라미터의 이름이 다른 두개의 메소드가 있다고 하자, 

add(3, 5)를 호출하면 어떤 메소드가 호출될까? 

두 메소드 다 호출되는데에 문제가 없다. 

컴퓨터에서는 3과 5가 number1인지 positiveNumber2인지 신경쓰지 않는다. 

단지 데이터타입이 무엇인지만 본다. 

만약 두번째 add메소드의 파라미터 중 int positiveNumber2가 double positiveNumber2 였다면 

add(3, 5)는 데이터타입이 일치한 첫번째 add메소드를 호출할 것이다. 

따라서 파라미터의 이름은 파라미터가 달라지는데에 영향이 없다. 

갯수의 경우

만약 add(3, 5, 6)라고 한다면 두 add 메소드 다 호출될 수 없다. 

파라미터의 갯수가 다르기 때문이다. 

 

# 오버로딩 개념이 나온 이유?

한 클래스 안에서 비슷한 기능을 하지만 파라미터가 달라지는 경우 

굳이 이름을 바꿀 필요없이 똑같은 이름으로 설정해 모아두기 위함이다.

 

예를 보자. 

나누기를 수행하는 division이라는 메소드를 만드는데 정수형 int 뿐 만 아니라 실수형 double도 계산이 되었으면 좋겠다.

그럴 경우 오버로딩을 이용할 수 있다. 

더보기

public static int division(int a, int b) {

    return a / b;

}

public static double division(double a, double b) {

    return a / b;

}

 

# 클래스 별 분리 

한 클래스에 역할이 다른 메소드들이 모여 있으면 보기에도, 사용하기에도 불편할 수 있다. 

그렇기 때문에 메소드들이 하는 역할과 어떤 필드들을 공통적으로 가지느냐에 따라서 클래스 별로 분리를 한다. 

즉, 클래스는 공통 분모를 잘 찾아서 만들도록 한다. 

이를 이용해서 계산기 프로그램을 만들어본다. 

 

# 계산기 프로그램

CalculatorEx.java

이 클래스는 사칙연산 메소드들이 모인 Calculator.java 클래스를 객체로 만들어 호출한 후 

결과를 출력하는 클래스이다. 

public class CalculatorEx {

	public static void main(String[] args) {
		Calculator cal = new Calculator(); // 객체 생성
		
		int myInt1 = 3; 
		int myInt2 = 5; 
		double myDouble1 = 3.14;
		double myDouble2 = 6.02;
		
		System.out.println(cal.add(myInt1, myInt2));
		

	}

}

 

Calculator.java

이 클래스는 사칙연산을 하는 메소드들을 모아둔 클래스이다. 


public class Calculator {

	public static void main(String[] args) {
	
		
	}
	
	
	// 더하기 
	public static int add(int a, int b) {
		return a + b;
	}
	
	public static double add(double a, double b) {
		return a + b;
	}
	public static double add(double a, int b) {
		return a + b;
	}
	
	// 빼기 
	public static int sub(int a, int b) {
		return a - b;
	}
	
	public static double sub(double a, double b) {
		return a - b;
	}
	public static double sub(double a, int b) {
		return a - b;
	}
	
	// 곱하기 
	public static int mult(int a, int b) {
		return a * b;
	}
	
	public static double mult(double a, double b) {
		return a * b;
	}
	public static double mult(double a, int b) {
		return a * b;
	}
	
	// 나누기 
	public static int divi(int a, int b) {
		return a / b;
	}
	
	public static double divi(double a, double b) {
		return a / b;
	}
	public static double divi(double a, int b) {
		return a / b;
	}
	
	
	
	
	
	


}

 

메소드 선언은 

(접근제한자 static) returnType name(parameter) 이지만 

위와 같이 객체를 만들어 메소드를 호출할 시엔 static을 생략해도 된다. 

만약, Calculator.add(3,5) 와 같이 객체를 생성하지 않고 호출하려면 static을 붙여야한다. 

 

# 접근제한자 활용

다른 곳에서 사용되는 메소드가 아니라면 무조건 private으로 설정하는 것이 좋다. 

choice 별로 별을 찍어주는 프로그램을 만들어보자. 

 

# 별찍어주기 프로그램

이 프로그램은 사용자가 1~3 중에 선택하면 그에 맞게 별을 찍어주는 프로그램이다. 

StarPrinter.java

이 클래스에서 사용자의 입력에 따른 별 찍기 메소드를 설정한다. 

모든 메소드는 private으로 설정했다.

따라서 

StarPrinterEx.java는 다른 클래스에 있기 때문에 접근할 수 없다.

그렇기 때문에 StarPrinter.java에서 별을 찍어주는 starPrintn의 메소드들이 selectNumber 메소드로 넘어간다. 

그런 후 selectNumber에서 lineNumber를 받아 switch 문에서 사용자로부터 어떤 선택을 받았는지 확인 한 후 

그에 맞는 starPrintn메소드를 수행하게 되는 것이다. 


public class StarPrinter {

	public void selectNumber(int choice, int lineNumber) {

		switch (choice) {
		case 1:
			starPrint1(lineNumber);
			break;
		case 2:
			starPrint2(lineNumber);
			break;
		case 3:
			starPrint3(lineNumber);
			break;
		}
	}

	// 별찍기 1번
	private void starPrint1(int lineNumber) {

		for (int i = 1; i <= lineNumber; i++) {
			String stars = "";
			for (int k = 1; k <= i; k++) {
				stars += "*";
			}
			System.out.println(stars);
		}
	}

	// 별찍기 2번
	private void starPrint2(int lineNumber) {
		for (int i = 1; i <= lineNumber; i++) {
			String stars = "";
			for (int k = i; k <= lineNumber; k++) {
				stars += "*";
			}
			System.out.println(stars);
		}
	}

	// 별찍기 3번
	private void starPrint3(int lineNumber) {
		for (int i = 1; i <= lineNumber; i++) {
			String stars = "";
			
			for (int k = 1; k <= lineNumber - i; k++) {
				stars += " ";
			}
			for (int k = 1; k <= i; k++) {
				stars += "*";
			}
			System.out.println(stars);
		}
	}

}

StarPrinterEx.java

이 클래스에서 사용자의 입력을 받아 StarPrinter.java 에서 그에 맞는 메소드를 가져올 것이다. 

package day04;

import java.util.Scanner;


public class StarPrinterEx {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("별 찍어주는 프로그램");
		
		System.out.print("출력할 별의 번호를 입력해주세요 : ");
		int choice = scan.nextInt();
		
		System.out.print("출력할 줄의 수를 입력해주세요 : ");
		int lineNumber = scan.nextInt();
		StarPrinter sp = new StarPrinter();

		sp.selectNumber(choice, lineNumber);
	
		scan.close();

	}

}

 

 

# 배열

배열이란 한 종류의 데이터 타입이 내가 지정한 크기만큼 모여있는 것이다. 

배열은 아래와 같이 선언할 수 있다. 

더보기

데이터타입[] 배열이름 = new 데이터타입[크기];

만약 크기가 5인 int 배열을 선언한다면? 

더보기

int[] array = new int[5];

배열은 각각 위치번호가 있다.

이를 index라고 부른다. 

배열의 index는 반드시 0 부터 시작한다. 

따라서 크기-1이 가장 마지막 인덱스 번호가 된다. 

(그래서 for문과 배열을 같이 쓰는 경우 for문이 0부터 시작했다면 종료 조건식에 = 가 붙지 않는다)

 

배열의 각 인덱스의 요소들(element)은 따로 초기화를 해주지 않아도 

기본형 데이터 타입의 경우엔 0 으로 초기화 된다.. 

String의 경우엔 null로 초기화된다. 

 

우리가 값을 넣을 때에는 array[0]를 커다른 변수명 처럼 사용하면 된다. 

더보기

array[0] = 5; 

위의 코드는 배열 array의 0번째 인덱스에 5라는 요소가 들어간 것이다. 

System.out.println(array[0]); 을 실행하면 5가 나온다. 

나머지 1, 2, 3, 4 는 그대로 0으로 초기화 되어 있다. 

 

# 인덱스 범위 오류 

인덱스의 가능 범위를 넘어설 경우. 

java.lang.ArrayIndexOutOfBoundsException 이란 오류가 발생한다. 

이 오류가 발생한 경우는 index가 잘못 잡혀있는 경우이니, index와 관련된 코드를 잘 살펴보자. 

 

# 인덱스 지정값

인덱스는 상수 외에 변수로도 지정할 수 있다. 

 

# 사용자로부터 입력을 받아 그 숫자를 차례대로 나열하는 프로그램

배열 5칸짜리 array를 생성한 후, 

그 array의 length (길이) 만큼 for문이 돌아가게 하여 배열의 요소 i값을 입력을 받는다. 

그런 후 다시 array의 길이 만큼 받은 array의 요소 i 값들을 출력한다. 


import java.util.Scanner;

public class ArrayPrac {

	public static void main(String[] args) {
		int[] array = new int[5];
		
		Scanner scan = new Scanner(System.in);
		
		for(int i = 0; i < array.length; i++) {
			System.out.print(i + " 번째 숫자를 입력해주세요 : ");
			array[i] = scan.nextInt();
			
		}
		
		for(int i = 0; i < array.length; i++) {
			System.out.println("array" + "["+i+"] = "+ array[i]);
		}
	

	}

}

 

 

# 배열 String 값

배열 요소가 String인 경우에는 어떻게 할까? 

String의 경우엔 기본형 데이터 타입인 int와 다르게 참조형 데이터 타입이다. 

그렇기 때문에 stack 에서 가진 값을 heap의 주소값에 따라 저장한다. 

따라서 String 값을 보려면 heap에 있는 주소값을 따라 String memory에서 찾아야 하는 것이다. 

String은 null로 초기화 되어있어 다른 값을 초기화 해줄 때까진 계속 null이다. 

 

null은 0과 다르게 '비어있음' 을 의미한다.

즉 값이 없는 것이다. 

그렇기 때문에 존재하지 않는 값을 보려고 하면 NullPointException 에러가 발생할 수 있기 때문에 

주의해야한다. 

public class ArrayPrac2 {

	public static void main(String[] args) {
		String[] stringArray = new String[5];
		
		for(int i = 0; i < stringArray.length; i++) {
			System.out.println(stringArray[i]);
		
			
			
		}

	}

}

 위의 코드를 실행하면 아래와 같이 null이 출력된다. 

아무런 값으로도 초기화를 하지 않은 상태이기 때문이다. 

 

 

# 이차원배열 

2차원배열은 똑같은 데이터타입의 배열이 또 모여있는 것이다. 

즉 배열 안의 배열이다. 

만약 

더보기

int[][] Array = new int[2][4]; 

라고 선언하면 어떤 형태의 배열이 될까?

[][][][]

[][][][] 

위와 같이 2행, 4열의 배열이 생성된다.